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

#ifndef LLVM_CLANG_AST_DECL_H
#define LLVM_CLANG_AST_DECL_H

#include "clang/AST/APValue.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PragmaKinds.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TrailingObjects.h"

namespace clang {
struct ASTTemplateArgumentListInfo;
class CXXTemporary;
class CompoundStmt;
class DependentFunctionTemplateSpecializationInfo;
class Expr;
class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class LabelStmt;
class MemberSpecializationInfo;
class NestedNameSpecifier;
class ParmVarDecl;
class Stmt;
class StringLiteral;
class TemplateArgumentList;
class TemplateParameterList;
class TypeAliasTemplateDecl;
class TypeLoc;
class UnresolvedSetImpl;
class VarTemplateDecl;

/// \brief A container of type source information.
///
/// A client can read the relevant info using TypeLoc wrappers, e.g:
/// @code
/// TypeLoc TL = TypeSourceInfo->getTypeLoc();
/// TL.getStartLoc().print(OS, SrcMgr);
/// @endcode
///
class TypeSourceInfo {
  QualType Ty;
  // Contains a memory block after the class, used for type source information,
  // allocated by ASTContext.
  friend class ASTContext;
  TypeSourceInfo(QualType ty) : Ty(ty) { }
public:
  /// \brief Return the type wrapped by this type source info.
  QualType getType() const { return Ty; }

  /// \brief Return the TypeLoc wrapper for the type source info.
  TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
  
  /// \brief Override the type stored in this TypeSourceInfo. Use with caution!
  void overrideType(QualType T) { Ty = T; }
};

/// TranslationUnitDecl - The top declaration context.
class TranslationUnitDecl : public Decl, public DeclContext {
  virtual void anchor();
  ASTContext &Ctx;

  /// The (most recently entered) anonymous namespace for this
  /// translation unit, if one has been created.
  NamespaceDecl *AnonymousNamespace;

  explicit TranslationUnitDecl(ASTContext &ctx);
public:
  ASTContext &getASTContext() const { return Ctx; }

  NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; }
  void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; }

  static TranslationUnitDecl *Create(ASTContext &C);
  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == TranslationUnit; }
  static DeclContext *castToDeclContext(const TranslationUnitDecl *D) {
    return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D));
  }
  static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<TranslationUnitDecl *>(const_cast<DeclContext*>(DC));
  }
};

/// \brief Represents a `#pragma comment` line. Always a child of
/// TranslationUnitDecl.
class PragmaCommentDecl final
    : public Decl,
      private llvm::TrailingObjects<PragmaCommentDecl, char> {
  virtual void anchor();

  PragmaMSCommentKind CommentKind;

  friend TrailingObjects;
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

  PragmaCommentDecl(TranslationUnitDecl *TU, SourceLocation CommentLoc,
                    PragmaMSCommentKind CommentKind)
      : Decl(PragmaComment, TU, CommentLoc), CommentKind(CommentKind) {}

public:
  static PragmaCommentDecl *Create(const ASTContext &C, TranslationUnitDecl *DC,
                                   SourceLocation CommentLoc,
                                   PragmaMSCommentKind CommentKind,
                                   StringRef Arg);
  static PragmaCommentDecl *CreateDeserialized(ASTContext &C, unsigned ID,
                                               unsigned ArgSize);

  PragmaMSCommentKind getCommentKind() const { return CommentKind; }

  StringRef getArg() const { return getTrailingObjects<char>(); }

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

/// \brief Represents a `#pragma detect_mismatch` line. Always a child of
/// TranslationUnitDecl.
class PragmaDetectMismatchDecl final
    : public Decl,
      private llvm::TrailingObjects<PragmaDetectMismatchDecl, char> {
  virtual void anchor();

  size_t ValueStart;

  friend TrailingObjects;
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

  PragmaDetectMismatchDecl(TranslationUnitDecl *TU, SourceLocation Loc,
                           size_t ValueStart)
      : Decl(PragmaDetectMismatch, TU, Loc), ValueStart(ValueStart) {}

public:
  static PragmaDetectMismatchDecl *Create(const ASTContext &C,
                                          TranslationUnitDecl *DC,
                                          SourceLocation Loc, StringRef Name,
                                          StringRef Value);
  static PragmaDetectMismatchDecl *
  CreateDeserialized(ASTContext &C, unsigned ID, unsigned NameValueSize);

  StringRef getName() const { return getTrailingObjects<char>(); }
  StringRef getValue() const { return getTrailingObjects<char>() + ValueStart; }

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

/// \brief Declaration context for names declared as extern "C" in C++. This
/// is neither the semantic nor lexical context for such declarations, but is
/// used to check for conflicts with other extern "C" declarations. Example:
///
/// \code
///   namespace N { extern "C" void f(); } // #1
///   void N::f() {}                       // #2
///   namespace M { extern "C" void f(); } // #3
/// \endcode
///
/// The semantic context of #1 is namespace N and its lexical context is the
/// LinkageSpecDecl; the semantic context of #2 is namespace N and its lexical
/// context is the TU. However, both declarations are also visible in the
/// extern "C" context.
///
/// The declaration at #3 finds it is a redeclaration of \c N::f through
/// lookup in the extern "C" context.
class ExternCContextDecl : public Decl, public DeclContext {
  virtual void anchor();

  explicit ExternCContextDecl(TranslationUnitDecl *TU)
    : Decl(ExternCContext, TU, SourceLocation()),
      DeclContext(ExternCContext) {}
public:
  static ExternCContextDecl *Create(const ASTContext &C,
                                    TranslationUnitDecl *TU);
  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ExternCContext; }
  static DeclContext *castToDeclContext(const ExternCContextDecl *D) {
    return static_cast<DeclContext *>(const_cast<ExternCContextDecl*>(D));
  }
  static ExternCContextDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<ExternCContextDecl *>(const_cast<DeclContext*>(DC));
  }
};

/// NamedDecl - This represents a decl with a name.  Many decls have names such
/// as ObjCMethodDecl, but not \@class, etc.
class NamedDecl : public Decl {
  virtual void anchor();
  /// Name - The name of this declaration, which is typically a normal
  /// identifier but may also be a special kind of name (C++
  /// constructor, Objective-C selector, etc.)
  DeclarationName Name;

private:
  NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY;

protected:
  NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
    : Decl(DK, DC, L), Name(N) { }

public:
  /// getIdentifier - Get the identifier that names this declaration,
  /// if there is one. This will return NULL if this declaration has
  /// no name (e.g., for an unnamed class) or if the name is a special
  /// name (C++ constructor, Objective-C selector, etc.).
  IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); }

  /// getName - Get the name of identifier for this declaration as a StringRef.
  /// This requires that the declaration have a name and that it be a simple
  /// identifier.
  StringRef getName() const {
    assert(Name.isIdentifier() && "Name is not a simple identifier");
    return getIdentifier() ? getIdentifier()->getName() : "";
  }

  /// getNameAsString - Get a human-readable name for the declaration, even if
  /// it is one of the special kinds of names (C++ constructor, Objective-C
  /// selector, etc).  Creating this name requires expensive string
  /// manipulation, so it should be called only when performance doesn't matter.
  /// For simple declarations, getNameAsCString() should suffice.
  //
  // FIXME: This function should be renamed to indicate that it is not just an
  // alternate form of getName(), and clients should move as appropriate.
  //
  // FIXME: Deprecated, move clients to getName().
  std::string getNameAsString() const { return Name.getAsString(); }

  virtual void printName(raw_ostream &os) const;

  /// getDeclName - Get the actual, stored name of the declaration,
  /// which may be a special name.
  DeclarationName getDeclName() const { return Name; }

  /// \brief Set the name of this declaration.
  void setDeclName(DeclarationName N) { Name = N; }

  /// printQualifiedName - Returns human-readable qualified name for
  /// declaration, like A::B::i, for i being member of namespace A::B.
  /// If declaration is not member of context which can be named (record,
  /// namespace), it will return same result as printName().
  /// Creating this name is expensive, so it should be called only when
  /// performance doesn't matter.
  void printQualifiedName(raw_ostream &OS) const;
  void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const;

  // FIXME: Remove string version.
  std::string getQualifiedNameAsString() const;

  /// getNameForDiagnostic - Appends a human-readable name for this
  /// declaration into the given stream.
  ///
  /// This is the method invoked by Sema when displaying a NamedDecl
  /// in a diagnostic.  It does not necessarily produce the same
  /// result as printName(); for example, class template
  /// specializations are printed with their template arguments.
  virtual void getNameForDiagnostic(raw_ostream &OS,
                                    const PrintingPolicy &Policy,
                                    bool Qualified) const;

  /// \brief Determine whether this declaration, if
  /// known to be well-formed within its context, will replace the
  /// declaration OldD if introduced into scope. A declaration will
  /// replace another declaration if, for example, it is a
  /// redeclaration of the same variable or function, but not if it is
  /// a declaration of a different kind (function vs. class) or an
  /// overloaded function.
  ///
  /// \param IsKnownNewer \c true if this declaration is known to be newer
  /// than \p OldD (for instance, if this declaration is newly-created).
  bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const;

  /// \brief Determine whether this declaration has linkage.
  bool hasLinkage() const;

  using Decl::isModulePrivate;
  using Decl::setModulePrivate;

  /// \brief Determine whether this declaration is a C++ class member.
  bool isCXXClassMember() const {
    const DeclContext *DC = getDeclContext();

    // C++0x [class.mem]p1:
    //   The enumerators of an unscoped enumeration defined in
    //   the class are members of the class.
    if (isa<EnumDecl>(DC))
      DC = DC->getRedeclContext();

    return DC->isRecord();
  }

  /// \brief Determine whether the given declaration is an instance member of
  /// a C++ class.
  bool isCXXInstanceMember() const;

  /// \brief Determine what kind of linkage this entity has.
  /// This is not the linkage as defined by the standard or the codegen notion
  /// of linkage. It is just an implementation detail that is used to compute
  /// those.
  Linkage getLinkageInternal() const;

  /// \brief Get the linkage from a semantic point of view. Entities in
  /// anonymous namespaces are external (in c++98).
  Linkage getFormalLinkage() const {
    return clang::getFormalLinkage(getLinkageInternal());
  }

  /// \brief True if this decl has external linkage.
  bool hasExternalFormalLinkage() const {
    return isExternalFormalLinkage(getLinkageInternal());
  }

  bool isExternallyVisible() const {
    return clang::isExternallyVisible(getLinkageInternal());
  }

  /// \brief Determines the visibility of this entity.
  Visibility getVisibility() const {
    return getLinkageAndVisibility().getVisibility();
  }

  /// \brief Determines the linkage and visibility of this entity.
  LinkageInfo getLinkageAndVisibility() const;

  /// Kinds of explicit visibility.
  enum ExplicitVisibilityKind {
    VisibilityForType,
    VisibilityForValue
  };

  /// \brief If visibility was explicitly specified for this
  /// declaration, return that visibility.
  Optional<Visibility>
  getExplicitVisibility(ExplicitVisibilityKind kind) const;

  /// \brief True if the computed linkage is valid. Used for consistency
  /// checking. Should always return true.
  bool isLinkageValid() const;

  /// \brief True if something has required us to compute the linkage
  /// of this declaration.
  ///
  /// Language features which can retroactively change linkage (like a
  /// typedef name for linkage purposes) may need to consider this,
  /// but hopefully only in transitory ways during parsing.
  bool hasLinkageBeenComputed() const {
    return hasCachedLinkage();
  }

  /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
  /// the underlying named decl.
  NamedDecl *getUnderlyingDecl() {
    // Fast-path the common case.
    if (this->getKind() != UsingShadow &&
        this->getKind() != ConstructorUsingShadow &&
        this->getKind() != ObjCCompatibleAlias &&
        this->getKind() != NamespaceAlias)
      return this;

    return getUnderlyingDeclImpl();
  }
  const NamedDecl *getUnderlyingDecl() const {
    return const_cast<NamedDecl*>(this)->getUnderlyingDecl();
  }

  NamedDecl *getMostRecentDecl() {
    return cast<NamedDecl>(static_cast<Decl *>(this)->getMostRecentDecl());
  }
  const NamedDecl *getMostRecentDecl() const {
    return const_cast<NamedDecl*>(this)->getMostRecentDecl();
  }

  ObjCStringFormatFamily getObjCFStringFormattingFamily() const;

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

inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
  ND.printName(OS);
  return OS;
}

/// LabelDecl - Represents the declaration of a label.  Labels also have a
/// corresponding LabelStmt, which indicates the position that the label was
/// defined at.  For normal labels, the location of the decl is the same as the
/// location of the statement.  For GNU local labels (__label__), the decl
/// location is where the __label__ is.
class LabelDecl : public NamedDecl {
  void anchor() override;
  LabelStmt *TheStmt;
  StringRef MSAsmName;
  bool MSAsmNameResolved;
  /// LocStart - For normal labels, this is the same as the main declaration
  /// label, i.e., the location of the identifier; for GNU local labels,
  /// this is the location of the __label__ keyword.
  SourceLocation LocStart;

  LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
            LabelStmt *S, SourceLocation StartL)
    : NamedDecl(Label, DC, IdentL, II),
      TheStmt(S),
      MSAsmNameResolved(false),
      LocStart(StartL) {}

public:
  static LabelDecl *Create(ASTContext &C, DeclContext *DC,
                           SourceLocation IdentL, IdentifierInfo *II);
  static LabelDecl *Create(ASTContext &C, DeclContext *DC,
                           SourceLocation IdentL, IdentifierInfo *II,
                           SourceLocation GnuLabelL);
  static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID);
  
  LabelStmt *getStmt() const { return TheStmt; }
  void setStmt(LabelStmt *T) { TheStmt = T; }

  bool isGnuLocal() const { return LocStart != getLocation(); }
  void setLocStart(SourceLocation L) { LocStart = L; }

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

  bool isMSAsmLabel() const { return MSAsmName.size() != 0; }
  bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; }
  void setMSAsmLabel(StringRef Name);
  StringRef getMSAsmLabel() const { return MSAsmName; }
  void setMSAsmLabelResolved() { MSAsmNameResolved = true; }

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

/// NamespaceDecl - Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext, 
                      public Redeclarable<NamespaceDecl> 
{
  /// LocStart - The starting location of the source range, pointing
  /// to either the namespace or the inline keyword.
  SourceLocation LocStart;
  /// RBraceLoc - The ending location of the source range.
  SourceLocation RBraceLoc;

  /// \brief A pointer to either the anonymous namespace that lives just inside
  /// this namespace or to the first namespace in the chain (the latter case
  /// only when this is not the first in the chain), along with a 
  /// boolean value indicating whether this is an inline namespace.
  llvm::PointerIntPair<NamespaceDecl *, 1, bool> AnonOrFirstNamespaceAndInline;

  NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
                SourceLocation StartLoc, SourceLocation IdLoc,
                IdentifierInfo *Id, NamespaceDecl *PrevDecl);

  typedef Redeclarable<NamespaceDecl> redeclarable_base;
  NamespaceDecl *getNextRedeclarationImpl() override;
  NamespaceDecl *getPreviousDeclImpl() override;
  NamespaceDecl *getMostRecentDeclImpl() override;

public:
  static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
                               bool Inline, SourceLocation StartLoc,
                               SourceLocation IdLoc, IdentifierInfo *Id,
                               NamespaceDecl *PrevDecl);

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

  typedef redeclarable_base::redecl_range redecl_range;
  typedef redeclarable_base::redecl_iterator 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;

  /// \brief Returns true if this is an anonymous namespace declaration.
  ///
  /// For example:
  /// \code
  ///   namespace {
  ///     ...
  ///   };
  /// \endcode
  /// q.v. C++ [namespace.unnamed]
  bool isAnonymousNamespace() const {
    return !getIdentifier();
  }

  /// \brief Returns true if this is an inline namespace declaration.
  bool isInline() const {
    return AnonOrFirstNamespaceAndInline.getInt();
  }

  /// \brief Set whether this is an inline namespace declaration.
  void setInline(bool Inline) {
    AnonOrFirstNamespaceAndInline.setInt(Inline);
  }

  /// \brief Get the original (first) namespace declaration.
  NamespaceDecl *getOriginalNamespace();

  /// \brief Get the original (first) namespace declaration.
  const NamespaceDecl *getOriginalNamespace() const;

  /// \brief Return true if this declaration is an original (first) declaration
  /// of the namespace. This is false for non-original (subsequent) namespace
  /// declarations and anonymous namespaces.
  bool isOriginalNamespace() const;

  /// \brief Retrieve the anonymous namespace nested inside this namespace,
  /// if any.
  NamespaceDecl *getAnonymousNamespace() const {
    return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer();
  }

  void setAnonymousNamespace(NamespaceDecl *D) {
    getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D);
  }

  /// Retrieves the canonical declaration of this namespace.
  NamespaceDecl *getCanonicalDecl() override {
    return getOriginalNamespace();
  }
  const NamespaceDecl *getCanonicalDecl() const {
    return getOriginalNamespace();
  }

  SourceRange getSourceRange() const override LLVM_READONLY {
    return SourceRange(LocStart, RBraceLoc);
  }

  SourceLocation getLocStart() const LLVM_READONLY { return LocStart; }
  SourceLocation getRBraceLoc() const { return RBraceLoc; }
  void setLocStart(SourceLocation L) { LocStart = L; }
  void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == Namespace; }
  static DeclContext *castToDeclContext(const NamespaceDecl *D) {
    return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D));
  }
  static NamespaceDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
  }

  friend class ASTDeclReader;
  friend class ASTDeclWriter;
};

/// ValueDecl - Represent the declaration of a variable (in which case it is
/// an lvalue) a function (in which case it is a function designator) or
/// an enum constant.
class ValueDecl : public NamedDecl {
  void anchor() override;
  QualType DeclType;

protected:
  ValueDecl(Kind DK, DeclContext *DC, SourceLocation L,
            DeclarationName N, QualType T)
    : NamedDecl(DK, DC, L, N), DeclType(T) {}
public:
  QualType getType() const { return DeclType; }
  void setType(QualType newType) { DeclType = newType; }

  /// \brief Determine whether this symbol is weakly-imported,
  ///        or declared with the weak or weak-ref attr.
  bool isWeak() const;

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

/// QualifierInfo - A struct with extended info about a syntactic
/// name qualifier, to be used for the case of out-of-line declarations.
struct QualifierInfo {
  NestedNameSpecifierLoc QualifierLoc;

  /// NumTemplParamLists - The number of "outer" template parameter lists.
  /// The count includes all of the template parameter lists that were matched
  /// against the template-ids occurring into the NNS and possibly (in the
  /// case of an explicit specialization) a final "template <>".
  unsigned NumTemplParamLists;

  /// TemplParamLists - A new-allocated array of size NumTemplParamLists,
  /// containing pointers to the "outer" template parameter lists.
  /// It includes all of the template parameter lists that were matched
  /// against the template-ids occurring into the NNS and possibly (in the
  /// case of an explicit specialization) a final "template <>".
  TemplateParameterList** TemplParamLists;

  /// Default constructor.
  QualifierInfo()
    : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(nullptr) {}

  /// setTemplateParameterListsInfo - Sets info about "outer" template
  /// parameter lists.
  void setTemplateParameterListsInfo(ASTContext &Context,
                                     ArrayRef<TemplateParameterList *> TPLists);

private:
  // Copy constructor and copy assignment are disabled.
  QualifierInfo(const QualifierInfo&) = delete;
  QualifierInfo& operator=(const QualifierInfo&) = delete;
};

/// \brief Represents a ValueDecl that came out of a declarator.
/// Contains type source information through TypeSourceInfo.
class DeclaratorDecl : public ValueDecl {
  // A struct representing both a TInfo and a syntactic qualifier,
  // to be used for the (uncommon) case of out-of-line declarations.
  struct ExtInfo : public QualifierInfo {
    TypeSourceInfo *TInfo;
  };

  llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo;

  /// InnerLocStart - The start of the source range for this declaration,
  /// ignoring outer template declarations.
  SourceLocation InnerLocStart;

  bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); }
  ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); }
  const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); }

protected:
  DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L,
                 DeclarationName N, QualType T, TypeSourceInfo *TInfo,
                 SourceLocation StartL)
    : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) {
  }

public:
  TypeSourceInfo *getTypeSourceInfo() const {
    return hasExtInfo()
      ? getExtInfo()->TInfo
      : DeclInfo.get<TypeSourceInfo*>();
  }
  void setTypeSourceInfo(TypeSourceInfo *TI) {
    if (hasExtInfo())
      getExtInfo()->TInfo = TI;
    else
      DeclInfo = TI;
  }

  /// getInnerLocStart - Return SourceLocation representing start of source
  /// range ignoring outer template declarations.
  SourceLocation getInnerLocStart() const { return InnerLocStart; }
  void setInnerLocStart(SourceLocation L) { InnerLocStart = L; }

  /// getOuterLocStart - Return SourceLocation representing start of source
  /// range taking into account any outer template declarations.
  SourceLocation getOuterLocStart() const;

  SourceRange getSourceRange() const override LLVM_READONLY;
  SourceLocation getLocStart() const LLVM_READONLY {
    return getOuterLocStart();
  }

  /// \brief Retrieve the nested-name-specifier that qualifies the name of this
  /// declaration, if it was present in the source.
  NestedNameSpecifier *getQualifier() const {
    return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
                        : nullptr;
  }

  /// \brief Retrieve the nested-name-specifier (with source-location
  /// information) that qualifies the name of this declaration, if it was
  /// present in the source.
  NestedNameSpecifierLoc getQualifierLoc() const {
    return hasExtInfo() ? getExtInfo()->QualifierLoc
                        : NestedNameSpecifierLoc();
  }

  void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);

  unsigned getNumTemplateParameterLists() const {
    return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
  }
  TemplateParameterList *getTemplateParameterList(unsigned index) const {
    assert(index < getNumTemplateParameterLists());
    return getExtInfo()->TemplParamLists[index];
  }
  void setTemplateParameterListsInfo(ASTContext &Context,
                                     ArrayRef<TemplateParameterList *> TPLists);

  SourceLocation getTypeSpecStartLoc() const;

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

  friend class ASTDeclReader;
  friend class ASTDeclWriter;
};

/// \brief Structure used to store a statement, the constant value to
/// which it was evaluated (if any), and whether or not the statement
/// is an integral constant expression (if known).
struct EvaluatedStmt {
  EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false),
                    CheckingICE(false), IsICE(false) { }

  /// \brief Whether this statement was already evaluated.
  bool WasEvaluated : 1;

  /// \brief Whether this statement is being evaluated.
  bool IsEvaluating : 1;

  /// \brief Whether we already checked whether this statement was an
  /// integral constant expression.
  bool CheckedICE : 1;

  /// \brief Whether we are checking whether this statement is an
  /// integral constant expression.
  bool CheckingICE : 1;

  /// \brief Whether this statement is an integral constant expression,
  /// or in C++11, whether the statement is a constant expression. Only
  /// valid if CheckedICE is true.
  bool IsICE : 1;

  Stmt *Value;
  APValue Evaluated;
};

/// VarDecl - An instance of this class is created to represent a variable
/// declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
  /// getStorageClassSpecifierString - Return the string used to
  /// specify the storage class \p SC.
  ///
  /// It is illegal to call this function with SC == None.
  static const char *getStorageClassSpecifierString(StorageClass SC);

  /// \brief Initialization styles.
  enum InitializationStyle {
    CInit,    ///< C-style initialization with assignment
    CallInit, ///< Call-style initialization (C++98)
    ListInit  ///< Direct list-initialization (C++11)
  };

  /// \brief Kinds of thread-local storage.
  enum TLSKind {
    TLS_None,   ///< Not a TLS variable.
    TLS_Static, ///< TLS with a known-constant initializer.
    TLS_Dynamic ///< TLS with a dynamic initializer.
  };

protected:
  // A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
  // have allocated the auxiliary struct of information there.
  //
  // TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for
  // this as *many* VarDecls are ParmVarDecls that don't have default
  // arguments. We could save some space by moving this pointer union to be
  // allocated in trailing space when necessary.
  typedef llvm::PointerUnion<Stmt *, EvaluatedStmt *> InitType;

  /// \brief The initializer for this variable or, for a ParmVarDecl, the
  /// C++ default argument.
  mutable InitType Init;

private:
  class VarDeclBitfields {
    friend class VarDecl;
    friend class ASTDeclReader;

    unsigned SClass : 3;
    unsigned TSCSpec : 2;
    unsigned InitStyle : 2;
  };
  enum { NumVarDeclBits = 7 };

  friend class ASTDeclReader;
  friend class StmtIteratorBase;
  friend class ASTNodeImporter;

protected:
  enum { NumParameterIndexBits = 8 };

  enum DefaultArgKind {
    DAK_None,
    DAK_Unparsed,
    DAK_Uninstantiated,
    DAK_Normal
  };

  class ParmVarDeclBitfields {
    friend class ParmVarDecl;
    friend class ASTDeclReader;

    unsigned : NumVarDeclBits;

    /// Whether this parameter inherits a default argument from a
    /// prior declaration.
    unsigned HasInheritedDefaultArg : 1;

    /// Describes the kind of default argument for this parameter. By default
    /// this is none. If this is normal, then the default argument is stored in
    /// the \c VarDecl initializer expression unless we were unable to parse
    /// (even an invalid) expression for the default argument.
    unsigned DefaultArgKind : 2;

    /// Whether this parameter undergoes K&R argument promotion.
    unsigned IsKNRPromoted : 1;

    /// Whether this parameter is an ObjC method parameter or not.
    unsigned IsObjCMethodParam : 1;

    /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier.
    /// Otherwise, the number of function parameter scopes enclosing
    /// the function parameter scope in which this parameter was
    /// declared.
    unsigned ScopeDepthOrObjCQuals : 7;

    /// The number of parameters preceding this parameter in the
    /// function parameter scope in which it was declared.
    unsigned ParameterIndex : NumParameterIndexBits;
  };

  class NonParmVarDeclBitfields {
    friend class VarDecl;
    friend class ImplicitParamDecl;
    friend class ASTDeclReader;

    unsigned : NumVarDeclBits;

    // FIXME: We need something similar to CXXRecordDecl::DefinitionData.
    /// \brief Whether this variable is a definition which was demoted due to
    /// module merge.
    unsigned IsThisDeclarationADemotedDefinition : 1;

    /// \brief Whether this variable is the exception variable in a C++ catch
    /// or an Objective-C @catch statement.
    unsigned ExceptionVar : 1;

    /// \brief Whether this local variable could be allocated in the return
    /// slot of its function, enabling the named return value optimization
    /// (NRVO).
    unsigned NRVOVariable : 1;

    /// \brief Whether this variable is the for-range-declaration in a C++0x
    /// for-range statement.
    unsigned CXXForRangeDecl : 1;

    /// \brief Whether this variable is an ARC pseudo-__strong
    /// variable;  see isARCPseudoStrong() for details.
    unsigned ARCPseudoStrong : 1;

    /// \brief Whether this variable is (C++1z) inline.
    unsigned IsInline : 1;

    /// \brief Whether this variable has (C++1z) inline explicitly specified.
    unsigned IsInlineSpecified : 1;

    /// \brief Whether this variable is (C++0x) constexpr.
    unsigned IsConstexpr : 1;

    /// \brief Whether this variable is the implicit variable for a lambda
    /// init-capture.
    unsigned IsInitCapture : 1;

    /// \brief Whether this local extern variable's previous declaration was
    /// declared in the same block scope. This controls whether we should merge
    /// the type of this declaration with its previous declaration.
    unsigned PreviousDeclInSameBlockScope : 1;

    /// Defines kind of the ImplicitParamDecl: 'this', 'self', 'vtt', '_cmd' or
    /// something else.
    unsigned ImplicitParamKind : 3;
  };

  union {
    unsigned AllBits;
    VarDeclBitfields VarDeclBits;
    ParmVarDeclBitfields ParmVarDeclBits;
    NonParmVarDeclBitfields NonParmVarDeclBits;
  };

  VarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
          SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
          TypeSourceInfo *TInfo, StorageClass SC);

  typedef Redeclarable<VarDecl> redeclarable_base;
  VarDecl *getNextRedeclarationImpl() override {
    return getNextRedeclaration();
  }
  VarDecl *getPreviousDeclImpl() override {
    return getPreviousDecl();
  }
  VarDecl *getMostRecentDeclImpl() override {
    return getMostRecentDecl();
  }

public:
  typedef redeclarable_base::redecl_range redecl_range;
  typedef redeclarable_base::redecl_iterator 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;

  static VarDecl *Create(ASTContext &C, DeclContext *DC,
                         SourceLocation StartLoc, SourceLocation IdLoc,
                         IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
                         StorageClass S);

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

  SourceRange getSourceRange() const override LLVM_READONLY;

  /// \brief Returns the storage class as written in the source. For the
  /// computed linkage of symbol, see getLinkage.
  StorageClass getStorageClass() const {
    return (StorageClass) VarDeclBits.SClass;
  }
  void setStorageClass(StorageClass SC);

  void setTSCSpec(ThreadStorageClassSpecifier TSC) {
    VarDeclBits.TSCSpec = TSC;
    assert(VarDeclBits.TSCSpec == TSC && "truncation");
  }
  ThreadStorageClassSpecifier getTSCSpec() const {
    return static_cast<ThreadStorageClassSpecifier>(VarDeclBits.TSCSpec);
  }
  TLSKind getTLSKind() const;

  /// hasLocalStorage - Returns true if a variable with function scope
  ///  is a non-static local variable.
  bool hasLocalStorage() const {
    if (getStorageClass() == SC_None) {
      // OpenCL v1.2 s6.5.3: The __constant or constant address space name is
      // used to describe variables allocated in global memory and which are
      // accessed inside a kernel(s) as read-only variables. As such, variables
      // in constant address space cannot have local storage.
      if (getType().getAddressSpace() == LangAS::opencl_constant)
        return false;
      // Second check is for C++11 [dcl.stc]p4.
      return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified;
    }

    // Global Named Register (GNU extension)
    if (getStorageClass() == SC_Register && !isLocalVarDeclOrParm())
      return false;

    // Return true for:  Auto, Register.
    // Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal.

    return getStorageClass() >= SC_Auto;
  }

  /// isStaticLocal - Returns true if a variable with function scope is a
  /// static local variable.
  bool isStaticLocal() const {
    return (getStorageClass() == SC_Static ||
            // C++11 [dcl.stc]p4
            (getStorageClass() == SC_None && getTSCSpec() == TSCS_thread_local))
      && !isFileVarDecl();
  }

  /// \brief Returns true if a variable has extern or __private_extern__
  /// storage.
  bool hasExternalStorage() const {
    return getStorageClass() == SC_Extern ||
           getStorageClass() == SC_PrivateExtern;
  }

  /// \brief Returns true for all variables that do not have local storage.
  ///
  /// This includes all global variables as well as static variables declared
  /// within a function.
  bool hasGlobalStorage() const { return !hasLocalStorage(); }

  /// \brief Get the storage duration of this variable, per C++ [basic.stc].
  StorageDuration getStorageDuration() const {
    return hasLocalStorage() ? SD_Automatic :
           getTSCSpec() ? SD_Thread : SD_Static;
  }

  /// \brief Compute the language linkage.
  LanguageLinkage getLanguageLinkage() const;

  /// \brief Determines whether this variable is a variable with
  /// external, C linkage.
  bool isExternC() const;

  /// \brief Determines whether this variable's context is, or is nested within,
  /// a C++ extern "C" linkage spec.
  bool isInExternCContext() const;

  /// \brief Determines whether this variable's context is, or is nested within,
  /// a C++ extern "C++" linkage spec.
  bool isInExternCXXContext() const;

  /// isLocalVarDecl - Returns true for local variable declarations
  /// other than parameters.  Note that this includes static variables
  /// inside of functions. It also includes variables inside blocks.
  ///
  ///   void foo() { int x; static int y; extern int z; }
  ///
  bool isLocalVarDecl() const {
    if (getKind() != Decl::Var && getKind() != Decl::Decomposition)
      return false;
    if (const DeclContext *DC = getLexicalDeclContext())
      return DC->getRedeclContext()->isFunctionOrMethod();
    return false;
  }

  /// \brief Similar to isLocalVarDecl but also includes parameters.
  bool isLocalVarDeclOrParm() const {
    return isLocalVarDecl() || getKind() == Decl::ParmVar;
  }

  /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
  /// excludes variables declared in blocks.
  bool isFunctionOrMethodVarDecl() const {
    if (getKind() != Decl::Var && getKind() != Decl::Decomposition)
      return false;
    const DeclContext *DC = getLexicalDeclContext()->getRedeclContext();
    return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block;
  }

  /// \brief Determines whether this is a static data member.
  ///
  /// This will only be true in C++, and applies to, e.g., the
  /// variable 'x' in:
  /// \code
  /// struct S {
  ///   static int x;
  /// };
  /// \endcode
  bool isStaticDataMember() const {
    // If it wasn't static, it would be a FieldDecl.
    return getKind() != Decl::ParmVar && getDeclContext()->isRecord();
  }

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

  enum DefinitionKind {
    DeclarationOnly,      ///< This declaration is only a declaration.
    TentativeDefinition,  ///< This declaration is a tentative definition.
    Definition            ///< This declaration is definitely a definition.
  };

  /// \brief Check whether this declaration is a definition. If this could be
  /// a tentative definition (in C), don't check whether there's an overriding
  /// definition.
  DefinitionKind isThisDeclarationADefinition(ASTContext &) const;
  DefinitionKind isThisDeclarationADefinition() const {
    return isThisDeclarationADefinition(getASTContext());
  }

  /// \brief Check whether this variable is defined in this
  /// translation unit.
  DefinitionKind hasDefinition(ASTContext &) const;
  DefinitionKind hasDefinition() const {
    return hasDefinition(getASTContext());
  }

  /// \brief Get the tentative definition that acts as the real definition in
  /// a TU. Returns null if there is a proper definition available.
  VarDecl *getActingDefinition();
  const VarDecl *getActingDefinition() const {
    return const_cast<VarDecl*>(this)->getActingDefinition();
  }

  /// \brief Get the real (not just tentative) definition for this declaration.
  VarDecl *getDefinition(ASTContext &);
  const VarDecl *getDefinition(ASTContext &C) const {
    return const_cast<VarDecl*>(this)->getDefinition(C);
  }
  VarDecl *getDefinition() {
    return getDefinition(getASTContext());
  }
  const VarDecl *getDefinition() const {
    return const_cast<VarDecl*>(this)->getDefinition();
  }

  /// \brief Determine whether this is or was instantiated from an out-of-line
  /// definition of a static data member.
  bool isOutOfLine() const override;

  /// isFileVarDecl - Returns true for file scoped variable declaration.
  bool isFileVarDecl() const {
    Kind K = getKind();
    if (K == ParmVar || K == ImplicitParam)
      return false;

    if (getLexicalDeclContext()->getRedeclContext()->isFileContext())
      return true;

    if (isStaticDataMember())
      return true;

    return false;
  }

  /// getAnyInitializer - Get the initializer for this variable, no matter which
  /// declaration it is attached to.
  const Expr *getAnyInitializer() const {
    const VarDecl *D;
    return getAnyInitializer(D);
  }

  /// getAnyInitializer - Get the initializer for this variable, no matter which
  /// declaration it is attached to. Also get that declaration.
  const Expr *getAnyInitializer(const VarDecl *&D) const;

  bool hasInit() const;
  const Expr *getInit() const {
    return const_cast<VarDecl *>(this)->getInit();
  }
  Expr *getInit();

  /// \brief Retrieve the address of the initializer expression.
  Stmt **getInitAddress();

  void setInit(Expr *I);

  /// \brief Determine whether this variable's value can be used in a
  /// constant expression, according to the relevant language standard.
  /// This only checks properties of the declaration, and does not check
  /// whether the initializer is in fact a constant expression.
  bool isUsableInConstantExpressions(ASTContext &C) const;

  EvaluatedStmt *ensureEvaluatedStmt() const;

  /// \brief Attempt to evaluate the value of the initializer attached to this
  /// declaration, and produce notes explaining why it cannot be evaluated or is
  /// not a constant expression. Returns a pointer to the value if evaluation
  /// succeeded, 0 otherwise.
  APValue *evaluateValue() const;
  APValue *evaluateValue(SmallVectorImpl<PartialDiagnosticAt> &Notes) const;

  /// \brief Return the already-evaluated value of this variable's
  /// initializer, or NULL if the value is not yet known. Returns pointer
  /// to untyped APValue if the value could not be evaluated.
  APValue *getEvaluatedValue() const;

  /// \brief Determines whether it is already known whether the
  /// initializer is an integral constant expression or not.
  bool isInitKnownICE() const;

  /// \brief Determines whether the initializer is an integral constant
  /// expression, or in C++11, whether the initializer is a constant
  /// expression.
  ///
  /// \pre isInitKnownICE()
  bool isInitICE() const;

  /// \brief Determine whether the value of the initializer attached to this
  /// declaration is an integral constant expression.
  bool checkInitIsICE() const;

  void setInitStyle(InitializationStyle Style) {
    VarDeclBits.InitStyle = Style;
  }

  /// \brief The style of initialization for this declaration.
  ///
  /// C-style initialization is "int x = 1;". Call-style initialization is
  /// a C++98 direct-initializer, e.g. "int x(1);". The Init expression will be
  /// the expression inside the parens or a "ClassType(a,b,c)" class constructor
  /// expression for class types. List-style initialization is C++11 syntax,
  /// e.g. "int x{1};". Clients can distinguish between different forms of
  /// initialization by checking this value. In particular, "int x = {1};" is
  /// C-style, "int x({1})" is call-style, and "int x{1};" is list-style; the
  /// Init expression in all three cases is an InitListExpr.
  InitializationStyle getInitStyle() const {
    return static_cast<InitializationStyle>(VarDeclBits.InitStyle);
  }
  /// \brief Whether the initializer is a direct-initializer (list or call).
  bool isDirectInit() const {
    return getInitStyle() != CInit;
  }

  /// \brief If this definition should pretend to be a declaration.
  bool isThisDeclarationADemotedDefinition() const {
    return isa<ParmVarDecl>(this) ? false :
      NonParmVarDeclBits.IsThisDeclarationADemotedDefinition;
  }

  /// \brief This is a definition which should be demoted to a declaration.
  ///
  /// In some cases (mostly module merging) we can end up with two visible
  /// definitions one of which needs to be demoted to a declaration to keep
  /// the AST invariants.
  void demoteThisDefinitionToDeclaration() {
    assert (isThisDeclarationADefinition() && "Not a definition!");
    assert (!isa<ParmVarDecl>(this) && "Cannot demote ParmVarDecls!");
    NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = 1;
  }

  /// \brief Determine whether this variable is the exception variable in a
  /// C++ catch statememt or an Objective-C \@catch statement.
  bool isExceptionVariable() const {
    return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ExceptionVar;
  }
  void setExceptionVariable(bool EV) {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.ExceptionVar = EV;
  }

  /// \brief Determine whether this local variable can be used with the named
  /// return value optimization (NRVO).
  ///
  /// The named return value optimization (NRVO) works by marking certain
  /// non-volatile local variables of class type as NRVO objects. These
  /// locals can be allocated within the return slot of their containing
  /// function, in which case there is no need to copy the object to the
  /// return slot when returning from the function. Within the function body,
  /// each return that returns the NRVO object will have this variable as its
  /// NRVO candidate.
  bool isNRVOVariable() const {
    return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.NRVOVariable;
  }
  void setNRVOVariable(bool NRVO) {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.NRVOVariable = NRVO;
  }

  /// \brief Determine whether this variable is the for-range-declaration in
  /// a C++0x for-range statement.
  bool isCXXForRangeDecl() const {
    return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.CXXForRangeDecl;
  }
  void setCXXForRangeDecl(bool FRD) {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.CXXForRangeDecl = FRD;
  }

  /// \brief Determine whether this variable is an ARC pseudo-__strong
  /// variable.  A pseudo-__strong variable has a __strong-qualified
  /// type but does not actually retain the object written into it.
  /// Generally such variables are also 'const' for safety.
  bool isARCPseudoStrong() const {
    return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ARCPseudoStrong;
  }
  void setARCPseudoStrong(bool ps) {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.ARCPseudoStrong = ps;
  }

  /// Whether this variable is (C++1z) inline.
  bool isInline() const {
    return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInline;
  }
  bool isInlineSpecified() const {
    return isa<ParmVarDecl>(this) ? false
                                  : NonParmVarDeclBits.IsInlineSpecified;
  }
  void setInlineSpecified() {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.IsInline = true;
    NonParmVarDeclBits.IsInlineSpecified = true;
  }
  void setImplicitlyInline() {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.IsInline = true;
  }

  /// Whether this variable is (C++11) constexpr.
  bool isConstexpr() const {
    return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsConstexpr;
  }
  void setConstexpr(bool IC) {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.IsConstexpr = IC;
  }

  /// Whether this variable is the implicit variable for a lambda init-capture.
  bool isInitCapture() const {
    return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsInitCapture;
  }
  void setInitCapture(bool IC) {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.IsInitCapture = IC;
  }

  /// Whether this local extern variable declaration's previous declaration
  /// was declared in the same block scope. Only correct in C++.
  bool isPreviousDeclInSameBlockScope() const {
    return isa<ParmVarDecl>(this)
               ? false
               : NonParmVarDeclBits.PreviousDeclInSameBlockScope;
  }
  void setPreviousDeclInSameBlockScope(bool Same) {
    assert(!isa<ParmVarDecl>(this));
    NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same;
  }

  /// \brief Retrieve the variable declaration from which this variable could
  /// be instantiated, if it is an instantiation (rather than a non-template).
  VarDecl *getTemplateInstantiationPattern() const;

  /// \brief If this variable is an instantiated static data member of a
  /// class template specialization, returns the templated static data member
  /// from which it was instantiated.
  VarDecl *getInstantiatedFromStaticDataMember() const;

  /// \brief If this variable is an instantiation of a variable template or a
  /// static data member of a class template, determine what kind of
  /// template specialization or instantiation this is.
  TemplateSpecializationKind getTemplateSpecializationKind() const;

  /// \brief If this variable is an instantiation of a variable template or a
  /// static data member of a class template, determine its point of
  /// instantiation.
  SourceLocation getPointOfInstantiation() const;

  /// \brief If this variable is an instantiation of a static data member of a
  /// class template specialization, retrieves the member specialization
  /// information.
  MemberSpecializationInfo *getMemberSpecializationInfo() const;

  /// \brief For a static data member that was instantiated from a static
  /// data member of a class template, set the template specialiation kind.
  void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
                        SourceLocation PointOfInstantiation = SourceLocation());

  /// \brief Specify that this variable is an instantiation of the
  /// static data member VD.
  void setInstantiationOfStaticDataMember(VarDecl *VD,
                                          TemplateSpecializationKind TSK);

  /// \brief Retrieves the variable template that is described by this
  /// variable declaration.
  ///
  /// Every variable template is represented as a VarTemplateDecl and a
  /// VarDecl. The former contains template properties (such as
  /// the template parameter lists) while the latter contains the
  /// actual description of the template's
  /// contents. VarTemplateDecl::getTemplatedDecl() retrieves the
  /// VarDecl that from a VarTemplateDecl, while
  /// getDescribedVarTemplate() retrieves the VarTemplateDecl from
  /// a VarDecl.
  VarTemplateDecl *getDescribedVarTemplate() const;

  void setDescribedVarTemplate(VarTemplateDecl *Template);

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

class ImplicitParamDecl : public VarDecl {
  void anchor() override;

public:
  /// Defines the kind of the implicit parameter: is this an implicit parameter
  /// with pointer to 'this', 'self', '_cmd', virtual table pointers, captured
  /// context or something else.
  enum ImplicitParamKind : unsigned {
    ObjCSelf,        /// Parameter for Objective-C 'self' argument
    ObjCCmd,         /// Parameter for Objective-C '_cmd' argument
    CXXThis,         /// Parameter for C++ 'this' argument
    CXXVTT,          /// Parameter for C++ virtual table pointers
    CapturedContext, /// Parameter for captured context
    Other,           /// Other implicit parameter
  };

  /// Create implicit parameter.
  static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC,
                                   SourceLocation IdLoc, IdentifierInfo *Id,
                                   QualType T, ImplicitParamKind ParamKind);
  static ImplicitParamDecl *Create(ASTContext &C, QualType T,
                                   ImplicitParamKind ParamKind);

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

  ImplicitParamDecl(ASTContext &C, DeclContext *DC, SourceLocation IdLoc,
                    IdentifierInfo *Id, QualType Type,
                    ImplicitParamKind ParamKind)
      : VarDecl(ImplicitParam, C, DC, IdLoc, IdLoc, Id, Type,
                /*TInfo=*/nullptr, SC_None) {
    NonParmVarDeclBits.ImplicitParamKind = ParamKind;
    setImplicit();
  }

  ImplicitParamDecl(ASTContext &C, QualType Type, ImplicitParamKind ParamKind)
      : VarDecl(ImplicitParam, C, /*DC=*/nullptr, SourceLocation(),
                SourceLocation(), /*Id=*/nullptr, Type,
                /*TInfo=*/nullptr, SC_None) {
    NonParmVarDeclBits.ImplicitParamKind = ParamKind;
    setImplicit();
  }

  /// Returns the implicit parameter kind.
  ImplicitParamKind getParameterKind() const {
    return static_cast<ImplicitParamKind>(NonParmVarDeclBits.ImplicitParamKind);
  }
  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == ImplicitParam; }
};

/// ParmVarDecl - Represents a parameter to a function.
class ParmVarDecl : public VarDecl {
public:
  enum { MaxFunctionScopeDepth = 255 };
  enum { MaxFunctionScopeIndex = 255 };

protected:
  ParmVarDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
              SourceLocation IdLoc, IdentifierInfo *Id, QualType T,
              TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
      : VarDecl(DK, C, DC, StartLoc, IdLoc, Id, T, TInfo, S) {
    assert(ParmVarDeclBits.HasInheritedDefaultArg == false);
    assert(ParmVarDeclBits.DefaultArgKind == DAK_None);
    assert(ParmVarDeclBits.IsKNRPromoted == false);
    assert(ParmVarDeclBits.IsObjCMethodParam == false);
    setDefaultArg(DefArg);
  }

public:
  static ParmVarDecl *Create(ASTContext &C, DeclContext *DC,
                             SourceLocation StartLoc,
                             SourceLocation IdLoc, IdentifierInfo *Id,
                             QualType T, TypeSourceInfo *TInfo,
                             StorageClass S, Expr *DefArg);

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

  SourceRange getSourceRange() const override LLVM_READONLY;

  void setObjCMethodScopeInfo(unsigned parameterIndex) {
    ParmVarDeclBits.IsObjCMethodParam = true;
    setParameterIndex(parameterIndex);
  }

  void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex) {
    assert(!ParmVarDeclBits.IsObjCMethodParam);

    ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth;
    assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth
           && "truncation!");

    setParameterIndex(parameterIndex);
  }

  bool isObjCMethodParameter() const {
    return ParmVarDeclBits.IsObjCMethodParam;
  }

  unsigned getFunctionScopeDepth() const {
    if (ParmVarDeclBits.IsObjCMethodParam) return 0;
    return ParmVarDeclBits.ScopeDepthOrObjCQuals;
  }

  /// Returns the index of this parameter in its prototype or method scope.
  unsigned getFunctionScopeIndex() const {
    return getParameterIndex();
  }

  ObjCDeclQualifier getObjCDeclQualifier() const {
    if (!ParmVarDeclBits.IsObjCMethodParam) return OBJC_TQ_None;
    return ObjCDeclQualifier(ParmVarDeclBits.ScopeDepthOrObjCQuals);
  }
  void setObjCDeclQualifier(ObjCDeclQualifier QTVal) {
    assert(ParmVarDeclBits.IsObjCMethodParam);
    ParmVarDeclBits.ScopeDepthOrObjCQuals = QTVal;
  }

  /// True if the value passed to this parameter must undergo
  /// K&R-style default argument promotion:
  ///
  /// C99 6.5.2.2.
  ///   If the expression that denotes the called function has a type
  ///   that does not include a prototype, the integer promotions are
  ///   performed on each argument, and arguments that have type float
  ///   are promoted to double.
  bool isKNRPromoted() const {
    return ParmVarDeclBits.IsKNRPromoted;
  }
  void setKNRPromoted(bool promoted) {
    ParmVarDeclBits.IsKNRPromoted = promoted;
  }

  Expr *getDefaultArg();
  const Expr *getDefaultArg() const {
    return const_cast<ParmVarDecl *>(this)->getDefaultArg();
  }

  void setDefaultArg(Expr *defarg);

  /// \brief Retrieve the source range that covers the entire default
  /// argument.
  SourceRange getDefaultArgRange() const;
  void setUninstantiatedDefaultArg(Expr *arg);
  Expr *getUninstantiatedDefaultArg();
  const Expr *getUninstantiatedDefaultArg() const {
    return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg();
  }

  /// hasDefaultArg - Determines whether this parameter has a default argument,
  /// either parsed or not.
  bool hasDefaultArg() const;

  /// hasUnparsedDefaultArg - Determines whether this parameter has a
  /// default argument that has not yet been parsed. This will occur
  /// during the processing of a C++ class whose member functions have
  /// default arguments, e.g.,
  /// @code
  ///   class X {
  ///   public:
  ///     void f(int x = 17); // x has an unparsed default argument now
  ///   }; // x has a regular default argument now
  /// @endcode
  bool hasUnparsedDefaultArg() const {
    return ParmVarDeclBits.DefaultArgKind == DAK_Unparsed;
  }

  bool hasUninstantiatedDefaultArg() const {
    return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated;
  }

  /// setUnparsedDefaultArg - Specify that this parameter has an
  /// unparsed default argument. The argument will be replaced with a
  /// real default argument via setDefaultArg when the class
  /// definition enclosing the function declaration that owns this
  /// default argument is completed.
  void setUnparsedDefaultArg() {
    ParmVarDeclBits.DefaultArgKind = DAK_Unparsed;
  }

  bool hasInheritedDefaultArg() const {
    return ParmVarDeclBits.HasInheritedDefaultArg;
  }

  void setHasInheritedDefaultArg(bool I = true) {
    ParmVarDeclBits.HasInheritedDefaultArg = I;
  }

  QualType getOriginalType() const;

  /// \brief Determine whether this parameter is actually a function
  /// parameter pack.
  bool isParameterPack() const;

  /// setOwningFunction - Sets the function declaration that owns this
  /// ParmVarDecl. Since ParmVarDecls are often created before the
  /// FunctionDecls that own them, this routine is required to update
  /// the DeclContext appropriately.
  void setOwningFunction(DeclContext *FD) { setDeclContext(FD); }

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

private:
  enum { ParameterIndexSentinel = (1 << NumParameterIndexBits) - 1 };

  void setParameterIndex(unsigned parameterIndex) {
    if (parameterIndex >= ParameterIndexSentinel) {
      setParameterIndexLarge(parameterIndex);
      return;
    }

    ParmVarDeclBits.ParameterIndex = parameterIndex;
    assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!");
  }
  unsigned getParameterIndex() const {
    unsigned d = ParmVarDeclBits.ParameterIndex;
    return d == ParameterIndexSentinel ? getParameterIndexLarge() : d;
  }

  void setParameterIndexLarge(unsigned parameterIndex);
  unsigned getParameterIndexLarge() const;
};

/// FunctionDecl - An instance of this class is created to represent a
/// function declaration or definition.
///
/// Since a given function can be declared several times in a program,
/// there may be several FunctionDecls that correspond to that
/// function. Only one of those FunctionDecls will be found when
/// traversing the list of declarations in the context of the
/// FunctionDecl (e.g., the translation unit); this FunctionDecl
/// contains all of the information known about the function. Other,
/// previous declarations of the function are available via the
/// getPreviousDecl() chain.
class FunctionDecl : public DeclaratorDecl, public DeclContext,
                     public Redeclarable<FunctionDecl> {
public:
  /// \brief The kind of templated function a FunctionDecl can be.
  enum TemplatedKind {
    TK_NonTemplate,
    TK_FunctionTemplate,
    TK_MemberSpecialization,
    TK_FunctionTemplateSpecialization,
    TK_DependentFunctionTemplateSpecialization
  };

private:
  /// ParamInfo - new[]'d array of pointers to VarDecls for the formal
  /// parameters of this function.  This is null if a prototype or if there are
  /// no formals.
  ParmVarDecl **ParamInfo;

  LazyDeclStmtPtr Body;

  // FIXME: This can be packed into the bitfields in DeclContext.
  // NOTE: VC++ packs bitfields poorly if the types differ.
  unsigned SClass : 3;
  unsigned IsInline : 1;
  unsigned IsInlineSpecified : 1;
protected:
  // This is shared by CXXConstructorDecl, CXXConversionDecl, and
  // CXXDeductionGuideDecl.
  unsigned IsExplicitSpecified : 1;
private:
  unsigned IsVirtualAsWritten : 1;
  unsigned IsPure : 1;
  unsigned HasInheritedPrototype : 1;
  unsigned HasWrittenPrototype : 1;
  unsigned IsDeleted : 1;
  unsigned IsTrivial : 1; // sunk from CXXMethodDecl
  unsigned IsDefaulted : 1; // sunk from CXXMethoDecl
  unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl
  unsigned HasImplicitReturnZero : 1;
  unsigned IsLateTemplateParsed : 1;
  unsigned IsConstexpr : 1;
  unsigned InstantiationIsPending:1;

  /// \brief Indicates if the function uses __try.
  unsigned UsesSEHTry : 1;

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

  /// Indicates if the function declaration will have a body, once we're done
  /// parsing it.
  unsigned WillHaveBody : 1;

  /// \brief End part of this FunctionDecl's source range.
  ///
  /// We could compute the full range in getSourceRange(). However, when we're
  /// dealing with a function definition deserialized from a PCH/AST file,
  /// we can only compute the full range once the function body has been
  /// de-serialized, so it's far better to have the (sometimes-redundant)
  /// EndRangeLoc.
  SourceLocation EndRangeLoc;

  /// \brief The template or declaration that this declaration
  /// describes or was instantiated from, respectively.
  ///
  /// For non-templates, this value will be NULL. For function
  /// declarations that describe a function template, this will be a
  /// pointer to a FunctionTemplateDecl. For member functions
  /// of class template specializations, this will be a MemberSpecializationInfo
  /// pointer containing information about the specialization.
  /// For function template specializations, this will be a
  /// FunctionTemplateSpecializationInfo, which contains information about
  /// the template being specialized and the template arguments involved in
  /// that specialization.
  llvm::PointerUnion4<FunctionTemplateDecl *,
                      MemberSpecializationInfo *,
                      FunctionTemplateSpecializationInfo *,
                      DependentFunctionTemplateSpecializationInfo *>
    TemplateOrSpecialization;

  /// DNLoc - Provides source/type location info for the
  /// declaration name embedded in the DeclaratorDecl base class.
  DeclarationNameLoc DNLoc;

  /// \brief Specify that this function declaration is actually a function
  /// template specialization.
  ///
  /// \param C the ASTContext.
  ///
  /// \param Template the function template that this function template
  /// specialization specializes.
  ///
  /// \param TemplateArgs the template arguments that produced this
  /// function template specialization from the template.
  ///
  /// \param InsertPos If non-NULL, the position in the function template
  /// specialization set where the function template specialization data will
  /// be inserted.
  ///
  /// \param TSK the kind of template specialization this is.
  ///
  /// \param TemplateArgsAsWritten location info of template arguments.
  ///
  /// \param PointOfInstantiation point at which the function template
  /// specialization was first instantiated.
  void setFunctionTemplateSpecialization(ASTContext &C,
                                         FunctionTemplateDecl *Template,
                                       const TemplateArgumentList *TemplateArgs,
                                         void *InsertPos,
                                         TemplateSpecializationKind TSK,
                          const TemplateArgumentListInfo *TemplateArgsAsWritten,
                                         SourceLocation PointOfInstantiation);

  /// \brief Specify that this record is an instantiation of the
  /// member function FD.
  void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD,
                                        TemplateSpecializationKind TSK);

  void setParams(ASTContext &C, ArrayRef<ParmVarDecl *> NewParamInfo);

protected:
  FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
               const DeclarationNameInfo &NameInfo, QualType T,
               TypeSourceInfo *TInfo, StorageClass S, bool isInlineSpecified,
               bool isConstexprSpecified)
      : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
                       StartLoc),
        DeclContext(DK), redeclarable_base(C), ParamInfo(nullptr), Body(),
        SClass(S), IsInline(isInlineSpecified),
        IsInlineSpecified(isInlineSpecified), IsExplicitSpecified(false),
        IsVirtualAsWritten(false), IsPure(false),
        HasInheritedPrototype(false), HasWrittenPrototype(true),
        IsDeleted(false), IsTrivial(false), IsDefaulted(false),
        IsExplicitlyDefaulted(false), HasImplicitReturnZero(false),
        IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified),
        InstantiationIsPending(false),
        UsesSEHTry(false), HasSkippedBody(false), WillHaveBody(false),
        EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(),
        DNLoc(NameInfo.getInfo()) {}

  typedef Redeclarable<FunctionDecl> redeclarable_base;
  FunctionDecl *getNextRedeclarationImpl() override {
    return getNextRedeclaration();
  }
  FunctionDecl *getPreviousDeclImpl() override {
    return getPreviousDecl();
  }
  FunctionDecl *getMostRecentDeclImpl() override {
    return getMostRecentDecl();
  }

public:
  typedef redeclarable_base::redecl_range redecl_range;
  typedef redeclarable_base::redecl_iterator 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;

  static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
                              SourceLocation StartLoc, SourceLocation NLoc,
                              DeclarationName N, QualType T,
                              TypeSourceInfo *TInfo,
                              StorageClass SC,
                              bool isInlineSpecified = false,
                              bool hasWrittenPrototype = true,
                              bool isConstexprSpecified = false) {
    DeclarationNameInfo NameInfo(N, NLoc);
    return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo,
                                SC,
                                isInlineSpecified, hasWrittenPrototype,
                                isConstexprSpecified);
  }

  static FunctionDecl *Create(ASTContext &C, DeclContext *DC,
                              SourceLocation StartLoc,
                              const DeclarationNameInfo &NameInfo,
                              QualType T, TypeSourceInfo *TInfo,
                              StorageClass SC,
                              bool isInlineSpecified,
                              bool hasWrittenPrototype,
                              bool isConstexprSpecified = false);

  static FunctionDecl *CreateDeserialized(ASTContext &C, unsigned ID);
                       
  DeclarationNameInfo getNameInfo() const {
    return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc);
  }

  void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy,
                            bool Qualified) const override;

  void setRangeEnd(SourceLocation E) { EndRangeLoc = E; }

  SourceRange getSourceRange() const override LLVM_READONLY;

  /// \brief Returns true if the function has a body (definition). The
  /// function body might be in any of the (re-)declarations of this
  /// function. The variant that accepts a FunctionDecl pointer will
  /// set that function declaration to the actual declaration
  /// containing the body (if there is one).
  bool hasBody(const FunctionDecl *&Definition) const;

  bool hasBody() const override {
    const FunctionDecl* Definition;
    return hasBody(Definition);
  }

  /// hasTrivialBody - Returns whether the function has a trivial body that does
  /// not require any specific codegen.
  bool hasTrivialBody() const;

  /// isDefined - Returns true if the function is defined at all, including
  /// a deleted definition. Except for the behavior when the function is
  /// deleted, behaves like hasBody.
  bool isDefined(const FunctionDecl *&Definition) const;

  virtual bool isDefined() const {
    const FunctionDecl* Definition;
    return isDefined(Definition);
  }

  /// \brief Get the definition for this declaration.
  FunctionDecl *getDefinition() {
    const FunctionDecl *Definition;
    if (isDefined(Definition))
      return const_cast<FunctionDecl *>(Definition);
    return nullptr;
  }
  const FunctionDecl *getDefinition() const {
    return const_cast<FunctionDecl *>(this)->getDefinition();
  }

  /// getBody - Retrieve the body (definition) of the function. The
  /// function body might be in any of the (re-)declarations of this
  /// function. The variant that accepts a FunctionDecl pointer will
  /// set that function declaration to the actual declaration
  /// containing the body (if there is one).
  /// NOTE: For checking if there is a body, use hasBody() instead, to avoid
  /// unnecessary AST de-serialization of the body.
  Stmt *getBody(const FunctionDecl *&Definition) const;

  Stmt *getBody() const override {
    const FunctionDecl* Definition;
    return getBody(Definition);
  }

  /// Returns whether this specific declaration of the function is also a
  /// definition that does not contain uninstantiated body.
  ///
  /// This does not determine whether the function has been defined (e.g., in a
  /// previous definition); for that information, use isDefined.
  ///
  bool isThisDeclarationADefinition() const {
    return IsDeleted || IsDefaulted || Body || IsLateTemplateParsed ||
      WillHaveBody || hasDefiningAttr();
  }

  /// doesThisDeclarationHaveABody - Returns whether this specific
  /// declaration of the function has a body - that is, if it is a non-
  /// deleted definition.
  bool doesThisDeclarationHaveABody() const {
    return Body || IsLateTemplateParsed;
  }

  void setBody(Stmt *B);
  void setLazyBody(uint64_t Offset) { Body = Offset; }

  /// Whether this function is variadic.
  bool isVariadic() const;

  /// Whether this function is marked as virtual explicitly.
  bool isVirtualAsWritten() const { return IsVirtualAsWritten; }
  void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; }

  /// Whether this virtual function is pure, i.e. makes the containing class
  /// abstract.
  bool isPure() const { return IsPure; }
  void setPure(bool P = true);

  /// Whether this templated function will be late parsed.
  bool isLateTemplateParsed() const { return IsLateTemplateParsed; }
  void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; }

  /// Whether this function is "trivial" in some specialized C++ senses.
  /// Can only be true for default constructors, copy constructors,
  /// copy assignment operators, and destructors.  Not meaningful until
  /// the class has been fully built by Sema.
  bool isTrivial() const { return IsTrivial; }
  void setTrivial(bool IT) { IsTrivial = IT; }

  /// Whether this function is defaulted per C++0x. Only valid for
  /// special member functions.
  bool isDefaulted() const { return IsDefaulted; }
  void setDefaulted(bool D = true) { IsDefaulted = D; }

  /// Whether this function is explicitly defaulted per C++0x. Only valid
  /// for special member functions.
  bool isExplicitlyDefaulted() const { return IsExplicitlyDefaulted; }
  void setExplicitlyDefaulted(bool ED = true) { IsExplicitlyDefaulted = ED; }

  /// Whether falling off this function implicitly returns null/zero.
  /// If a more specific implicit return value is required, front-ends
  /// should synthesize the appropriate return statements.
  bool hasImplicitReturnZero() const { return HasImplicitReturnZero; }
  void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; }

  /// \brief Whether this function has a prototype, either because one
  /// was explicitly written or because it was "inherited" by merging
  /// a declaration without a prototype with a declaration that has a
  /// prototype.
  bool hasPrototype() const {
    return HasWrittenPrototype || HasInheritedPrototype;
  }

  bool hasWrittenPrototype() const { return HasWrittenPrototype; }

  /// \brief Whether this function inherited its prototype from a
  /// previous declaration.
  bool hasInheritedPrototype() const { return HasInheritedPrototype; }
  void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; }

  /// Whether this is a (C++11) constexpr function or constexpr constructor.
  bool isConstexpr() const { return IsConstexpr; }
  void setConstexpr(bool IC) { IsConstexpr = IC; }

  /// \brief Whether the instantiation of this function is pending.
  /// This bit is set when the decision to instantiate this function is made
  /// and unset if and when the function body is created. That leaves out
  /// cases where instantiation did not happen because the template definition
  /// was not seen in this TU. This bit remains set in those cases, under the
  /// assumption that the instantiation will happen in some other TU.
  bool instantiationIsPending() const { return InstantiationIsPending; }
  void setInstantiationIsPending(bool IC) { InstantiationIsPending = IC; }

  /// \brief Indicates the function uses __try.
  bool usesSEHTry() const { return UsesSEHTry; }
  void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }

  /// \brief Whether this function has been deleted.
  ///
  /// A function that is "deleted" (via the C++0x "= delete" syntax)
  /// acts like a normal function, except that it cannot actually be
  /// called or have its address taken. Deleted functions are
  /// typically used in C++ overload resolution to attract arguments
  /// whose type or lvalue/rvalue-ness would permit the use of a
  /// different overload that would behave incorrectly. For example,
  /// one might use deleted functions to ban implicit conversion from
  /// a floating-point number to an Integer type:
  ///
  /// @code
  /// struct Integer {
  ///   Integer(long); // construct from a long
  ///   Integer(double) = delete; // no construction from float or double
  ///   Integer(long double) = delete; // no construction from long double
  /// };
  /// @endcode
  // If a function is deleted, its first declaration must be.
  bool isDeleted() const { return getCanonicalDecl()->IsDeleted; }
  bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; }
  void setDeletedAsWritten(bool D = true) { IsDeleted = D; }

  /// \brief Determines whether this function is "main", which is the
  /// entry point into an executable program.
  bool isMain() const;

  /// \brief Determines whether this function is a MSVCRT user defined entry
  /// point.
  bool isMSVCRTEntryPoint() const;

  /// \brief Determines whether this operator new or delete is one
  /// of the reserved global placement operators:
  ///    void *operator new(size_t, void *);
  ///    void *operator new[](size_t, void *);
  ///    void operator delete(void *, void *);
  ///    void operator delete[](void *, void *);
  /// These functions have special behavior under [new.delete.placement]:
  ///    These functions are reserved, a C++ program may not define
  ///    functions that displace the versions in the Standard C++ library.
  ///    The provisions of [basic.stc.dynamic] do not apply to these
  ///    reserved placement forms of operator new and operator delete.
  ///
  /// This function must be an allocation or deallocation function.
  bool isReservedGlobalPlacementOperator() const;

  /// \brief Determines whether this function is one of the replaceable
  /// global allocation functions:
  ///    void *operator new(size_t);
  ///    void *operator new(size_t, const std::nothrow_t &) noexcept;
  ///    void *operator new[](size_t);
  ///    void *operator new[](size_t, const std::nothrow_t &) noexcept;
  ///    void operator delete(void *) noexcept;
  ///    void operator delete(void *, std::size_t) noexcept;      [C++1y]
  ///    void operator delete(void *, const std::nothrow_t &) noexcept;
  ///    void operator delete[](void *) noexcept;
  ///    void operator delete[](void *, std::size_t) noexcept;    [C++1y]
  ///    void operator delete[](void *, const std::nothrow_t &) noexcept;
  /// These functions have special behavior under C++1y [expr.new]:
  ///    An implementation is allowed to omit a call to a replaceable global
  ///    allocation function. [...]
  ///
  /// If this function is an aligned allocation/deallocation function, return
  /// true through IsAligned.
  bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const;

  /// Compute the language linkage.
  LanguageLinkage getLanguageLinkage() const;

  /// \brief Determines whether this function is a function with
  /// external, C linkage.
  bool isExternC() const;

  /// \brief Determines whether this function's context is, or is nested within,
  /// a C++ extern "C" linkage spec.
  bool isInExternCContext() const;

  /// \brief Determines whether this function's context is, or is nested within,
  /// a C++ extern "C++" linkage spec.
  bool isInExternCXXContext() const;

  /// \brief Determines whether this is a global function.
  bool isGlobal() const;

  /// \brief Determines whether this function is known to be 'noreturn', through
  /// an attribute on its declaration or its type.
  bool isNoReturn() const;

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

  /// True if this function will eventually have a body, once it's fully parsed.
  bool willHaveBody() const { return WillHaveBody; }
  void setWillHaveBody(bool V = true) { WillHaveBody = V; }

  void setPreviousDeclaration(FunctionDecl * PrevDecl);

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

  unsigned getBuiltinID() const;

  // ArrayRef interface to parameters.
  ArrayRef<ParmVarDecl *> parameters() const {
    return {ParamInfo, getNumParams()};
  }
  MutableArrayRef<ParmVarDecl *> parameters() {
    return {ParamInfo, getNumParams()};
  }

  // Iterator access to formal parameters.
  typedef MutableArrayRef<ParmVarDecl *>::iterator param_iterator;
  typedef ArrayRef<ParmVarDecl *>::const_iterator param_const_iterator;
  bool param_empty() const { return parameters().empty(); }
  param_iterator param_begin() { return parameters().begin(); }
  param_iterator param_end() { return parameters().end(); }
  param_const_iterator param_begin() const { return parameters().begin(); }
  param_const_iterator param_end() const { return parameters().end(); }
  size_t param_size() const { return parameters().size(); }

  /// getNumParams - Return the number of parameters this function must have
  /// based on its FunctionType.  This is the length of the ParamInfo array
  /// after it has been created.
  unsigned getNumParams() const;

  const ParmVarDecl *getParamDecl(unsigned i) const {
    assert(i < getNumParams() && "Illegal param #");
    return ParamInfo[i];
  }
  ParmVarDecl *getParamDecl(unsigned i) {
    assert(i < getNumParams() && "Illegal param #");
    return ParamInfo[i];
  }
  void setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
    setParams(getASTContext(), NewParamInfo);
  }

  /// getMinRequiredArguments - Returns the minimum number of arguments
  /// needed to call this function. This may be fewer than the number of
  /// function parameters, if some of the parameters have default
  /// arguments (in C++).
  unsigned getMinRequiredArguments() const;

  QualType getReturnType() const {
    assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
    return getType()->getAs<FunctionType>()->getReturnType();
  }

  /// \brief Attempt to compute an informative source range covering the
  /// function return type. This may omit qualifiers and other information with
  /// limited representation in the AST.
  SourceRange getReturnTypeSourceRange() const;

  /// \brief Attempt to compute an informative source range covering the
  /// function exception specification, if any.
  SourceRange getExceptionSpecSourceRange() const;

  /// \brief Determine the type of an expression that calls this function.
  QualType getCallResultType() const {
    assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!");
    return getType()->getAs<FunctionType>()->getCallResultType(getASTContext());
  }

  /// \brief Returns the WarnUnusedResultAttr that is either declared on this
  /// function, or its return type declaration.
  const Attr *getUnusedResultAttr() const;

  /// \brief Returns true if this function or its return type has the
  /// warn_unused_result attribute.
  bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; }

  /// \brief Returns the storage class as written in the source. For the
  /// computed linkage of symbol, see getLinkage.
  StorageClass getStorageClass() const { return StorageClass(SClass); }

  /// \brief Determine whether the "inline" keyword was specified for this
  /// function.
  bool isInlineSpecified() const { return IsInlineSpecified; }

  /// Set whether the "inline" keyword was specified for this function.
  void setInlineSpecified(bool I) {
    IsInlineSpecified = I;
    IsInline = I;
  }

  /// Flag that this function is implicitly inline.
  void setImplicitlyInline() {
    IsInline = true;
  }

  /// \brief Determine whether this function should be inlined, because it is
  /// either marked "inline" or "constexpr" or is a member function of a class
  /// that was defined in the class body.
  bool isInlined() const { return IsInline; }

  bool isInlineDefinitionExternallyVisible() const;

  bool isMSExternInline() const;

  bool doesDeclarationForceExternallyVisibleDefinition() const;

  /// isOverloadedOperator - Whether this function declaration
  /// represents an C++ overloaded operator, e.g., "operator+".
  bool isOverloadedOperator() const {
    return getOverloadedOperator() != OO_None;
  }

  OverloadedOperatorKind getOverloadedOperator() const;

  const IdentifierInfo *getLiteralIdentifier() const;

  /// \brief If this function is an instantiation of a member function
  /// of a class template specialization, retrieves the function from
  /// which it was instantiated.
  ///
  /// This routine will return non-NULL for (non-templated) member
  /// functions of class templates and for instantiations of function
  /// templates. For example, given:
  ///
  /// \code
  /// template<typename T>
  /// struct X {
  ///   void f(T);
  /// };
  /// \endcode
  ///
  /// The declaration for X<int>::f is a (non-templated) FunctionDecl
  /// whose parent is the class template specialization X<int>. For
  /// this declaration, getInstantiatedFromFunction() will return
  /// the FunctionDecl X<T>::A. When a complete definition of
  /// X<int>::A is required, it will be instantiated from the
  /// declaration returned by getInstantiatedFromMemberFunction().
  FunctionDecl *getInstantiatedFromMemberFunction() const;

  /// \brief What kind of templated function this is.
  TemplatedKind getTemplatedKind() const;

  /// \brief If this function is an instantiation of a member function of a
  /// class template specialization, retrieves the member specialization
  /// information.
  MemberSpecializationInfo *getMemberSpecializationInfo() const;

  /// \brief Specify that this record is an instantiation of the
  /// member function FD.
  void setInstantiationOfMemberFunction(FunctionDecl *FD,
                                        TemplateSpecializationKind TSK) {
    setInstantiationOfMemberFunction(getASTContext(), FD, TSK);
  }

  /// \brief Retrieves the function template that is described by this
  /// function declaration.
  ///
  /// Every function template is represented as a FunctionTemplateDecl
  /// and a FunctionDecl (or something derived from FunctionDecl). The
  /// former contains template properties (such as the template
  /// parameter lists) while the latter contains the actual
  /// description of the template's
  /// contents. FunctionTemplateDecl::getTemplatedDecl() retrieves the
  /// FunctionDecl that describes the function template,
  /// getDescribedFunctionTemplate() retrieves the
  /// FunctionTemplateDecl from a FunctionDecl.
  FunctionTemplateDecl *getDescribedFunctionTemplate() const;

  void setDescribedFunctionTemplate(FunctionTemplateDecl *Template);

  /// \brief Determine whether this function is a function template
  /// specialization.
  bool isFunctionTemplateSpecialization() const {
    return getPrimaryTemplate() != nullptr;
  }

  /// \brief Retrieve the class scope template pattern that this function
  ///  template specialization is instantiated from.
  FunctionDecl *getClassScopeSpecializationPattern() const;

  /// \brief If this function is actually a function template specialization,
  /// retrieve information about this function template specialization.
  /// Otherwise, returns NULL.
  FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const;

  /// \brief Determines whether this function is a function template
  /// specialization or a member of a class template specialization that can
  /// be implicitly instantiated.
  bool isImplicitlyInstantiable() const;

  /// \brief Determines if the given function was instantiated from a
  /// function template.
  bool isTemplateInstantiation() const;

  /// \brief Retrieve the function declaration from which this function could
  /// be instantiated, if it is an instantiation (rather than a non-template
  /// or a specialization, for example).
  FunctionDecl *getTemplateInstantiationPattern() const;

  /// \brief Retrieve the primary template that this function template
  /// specialization either specializes or was instantiated from.
  ///
  /// If this function declaration is not a function template specialization,
  /// returns NULL.
  FunctionTemplateDecl *getPrimaryTemplate() const;

  /// \brief Retrieve the template arguments used to produce this function
  /// template specialization from the primary template.
  ///
  /// If this function declaration is not a function template specialization,
  /// returns NULL.
  const TemplateArgumentList *getTemplateSpecializationArgs() const;

  /// \brief Retrieve the template argument list as written in the sources,
  /// if any.
  ///
  /// If this function declaration is not a function template specialization
  /// or if it had no explicit template argument list, returns NULL.
  /// Note that it an explicit template argument list may be written empty,
  /// e.g., template<> void foo<>(char* s);
  const ASTTemplateArgumentListInfo*
  getTemplateSpecializationArgsAsWritten() const;

  /// \brief Specify that this function declaration is actually a function
  /// template specialization.
  ///
  /// \param Template the function template that this function template
  /// specialization specializes.
  ///
  /// \param TemplateArgs the template arguments that produced this
  /// function template specialization from the template.
  ///
  /// \param InsertPos If non-NULL, the position in the function template
  /// specialization set where the function template specialization data will
  /// be inserted.
  ///
  /// \param TSK the kind of template specialization this is.
  ///
  /// \param TemplateArgsAsWritten location info of template arguments.
  ///
  /// \param PointOfInstantiation point at which the function template
  /// specialization was first instantiated.
  void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template,
                const TemplateArgumentList *TemplateArgs,
                void *InsertPos,
                TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
                const TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr,
                SourceLocation PointOfInstantiation = SourceLocation()) {
    setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs,
                                      InsertPos, TSK, TemplateArgsAsWritten,
                                      PointOfInstantiation);
  }

  /// \brief Specifies that this function declaration is actually a
  /// dependent function template specialization.
  void setDependentTemplateSpecialization(ASTContext &Context,
                             const UnresolvedSetImpl &Templates,
                      const TemplateArgumentListInfo &TemplateArgs);

  DependentFunctionTemplateSpecializationInfo *
  getDependentSpecializationInfo() const;

  /// \brief Determine what kind of template instantiation this function
  /// represents.
  TemplateSpecializationKind getTemplateSpecializationKind() const;

  /// \brief Determine what kind of template instantiation this function
  /// represents.
  void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
                        SourceLocation PointOfInstantiation = SourceLocation());

  /// \brief Retrieve the (first) point of instantiation of a function template
  /// specialization or a member of a class template specialization.
  ///
  /// \returns the first point of instantiation, if this function was
  /// instantiated from a template; otherwise, returns an invalid source
  /// location.
  SourceLocation getPointOfInstantiation() const;

  /// \brief Determine whether this is or was instantiated from an out-of-line
  /// definition of a member function.
  bool isOutOfLine() const override;

  /// \brief Identify a memory copying or setting function.
  /// If the given function is a memory copy or setting function, returns
  /// the corresponding Builtin ID. If the function is not a memory function,
  /// returns 0.
  unsigned getMemoryFunctionKind() const;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) {
    return K >= firstFunction && K <= lastFunction;
  }
  static DeclContext *castToDeclContext(const FunctionDecl *D) {
    return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D));
  }
  static FunctionDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC));
  }

  friend class ASTDeclReader;
  friend class ASTDeclWriter;
};


/// FieldDecl - An instance of this class is created by Sema::ActOnField to
/// represent a member of a struct/union/class.
class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
  // FIXME: This can be packed into the bitfields in Decl.
  unsigned Mutable : 1;
  mutable unsigned CachedFieldIndex : 31;

  /// The kinds of value we can store in InitializerOrBitWidth.
  ///
  /// Note that this is compatible with InClassInitStyle except for
  /// ISK_CapturedVLAType.
  enum InitStorageKind {
    /// If the pointer is null, there's nothing special.  Otherwise,
    /// this is a bitfield and the pointer is the Expr* storing the
    /// bit-width.
    ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit,

    /// The pointer is an (optional due to delayed parsing) Expr*
    /// holding the copy-initializer.
    ISK_InClassCopyInit = (unsigned) ICIS_CopyInit,

    /// The pointer is an (optional due to delayed parsing) Expr*
    /// holding the list-initializer.
    ISK_InClassListInit = (unsigned) ICIS_ListInit,

    /// The pointer is a VariableArrayType* that's been captured;
    /// the enclosing context is a lambda or captured statement.
    ISK_CapturedVLAType,
  };

  /// \brief Storage for either the bit-width, the in-class
  /// initializer, or the captured variable length array bound.
  ///
  /// We can safely combine these because in-class initializers are
  /// not permitted for bit-fields, and both are exclusive with VLA
  /// captures.
  ///
  /// If the storage kind is ISK_InClassCopyInit or
  /// ISK_InClassListInit, but the initializer is null, then this
  /// field has an in-class initializer which has not yet been parsed
  /// and attached.
  llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage;
protected:
  FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
            SourceLocation IdLoc, IdentifierInfo *Id,
            QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
            InClassInitStyle InitStyle)
    : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
      Mutable(Mutable), CachedFieldIndex(0),
      InitStorage(BW, (InitStorageKind) InitStyle) {
    assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield");
  }

public:
  static FieldDecl *Create(const ASTContext &C, DeclContext *DC,
                           SourceLocation StartLoc, SourceLocation IdLoc,
                           IdentifierInfo *Id, QualType T,
                           TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
                           InClassInitStyle InitStyle);

  static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID);
  
  /// getFieldIndex - Returns the index of this field within its record,
  /// as appropriate for passing to ASTRecordLayout::getFieldOffset.
  unsigned getFieldIndex() const;

  /// isMutable - Determines whether this field is mutable (C++ only).
  bool isMutable() const { return Mutable; }

  /// \brief Determines whether this field is a bitfield.
  bool isBitField() const {
    return InitStorage.getInt() == ISK_BitWidthOrNothing &&
           InitStorage.getPointer() != nullptr;
  }

  /// @brief Determines whether this is an unnamed bitfield.
  bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); }

  /// isAnonymousStructOrUnion - Determines whether this field is a
  /// representative for an anonymous struct or union. Such fields are
  /// unnamed and are implicitly generated by the implementation to
  /// store the data for the anonymous union or struct.
  bool isAnonymousStructOrUnion() const;

  Expr *getBitWidth() const {
    return isBitField()
               ? static_cast<Expr *>(InitStorage.getPointer())
               : nullptr;
  }
  unsigned getBitWidthValue(const ASTContext &Ctx) const;

  /// setBitWidth - Set the bit-field width for this member.
  // Note: used by some clients (i.e., do not remove it).
  void setBitWidth(Expr *Width) {
    assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
           InitStorage.getPointer() == nullptr &&
           "bit width, initializer or captured type already set");
    InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing);
  }

  /// removeBitWidth - Remove the bit-field width from this member.
  // Note: used by some clients (i.e., do not remove it).
  void removeBitWidth() {
    assert(isBitField() && "no bitfield width to remove");
    InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
  }

  /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which
  /// this field has.
  InClassInitStyle getInClassInitStyle() const {
    InitStorageKind storageKind = InitStorage.getInt();
    return (storageKind == ISK_CapturedVLAType
              ? ICIS_NoInit : (InClassInitStyle) storageKind);
  }

  /// hasInClassInitializer - Determine whether this member has a C++11 in-class
  /// initializer.
  bool hasInClassInitializer() const {
    return getInClassInitStyle() != ICIS_NoInit;
  }

  /// getInClassInitializer - Get the C++11 in-class initializer for this
  /// member, or null if one has not been set. If a valid declaration has an
  /// in-class initializer, but this returns null, then we have not parsed and
  /// attached it yet.
  Expr *getInClassInitializer() const {
    return hasInClassInitializer()
               ? static_cast<Expr *>(InitStorage.getPointer())
               : nullptr;
  }

  /// setInClassInitializer - Set the C++11 in-class initializer for this
  /// member.
  void setInClassInitializer(Expr *Init) {
    assert(hasInClassInitializer() &&
           InitStorage.getPointer() == nullptr &&
           "bit width, initializer or captured type already set");
    InitStorage.setPointer(Init);
  }

  /// removeInClassInitializer - Remove the C++11 in-class initializer from this
  /// member.
  void removeInClassInitializer() {
    assert(hasInClassInitializer() && "no initializer to remove");
    InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
  }

  /// \brief Determine whether this member captures the variable length array
  /// type.
  bool hasCapturedVLAType() const {
    return InitStorage.getInt() == ISK_CapturedVLAType;
  }

  /// \brief Get the captured variable length array type.
  const VariableArrayType *getCapturedVLAType() const {
    return hasCapturedVLAType() ? static_cast<const VariableArrayType *>(
                                      InitStorage.getPointer())
                                : nullptr;
  }
  /// \brief Set the captured variable length array type for this field.
  void setCapturedVLAType(const VariableArrayType *VLAType);

  /// getParent - Returns the parent of this field declaration, which
  /// is the struct in which this field is defined.
  const RecordDecl *getParent() const {
    return cast<RecordDecl>(getDeclContext());
  }

  RecordDecl *getParent() {
    return cast<RecordDecl>(getDeclContext());
  }

  SourceRange getSourceRange() const override LLVM_READONLY;

  /// Retrieves the canonical declaration of this field.
  FieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
  const FieldDecl *getCanonicalDecl() const { return getFirstDecl(); }

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

  friend class ASTDeclReader;
  friend class ASTDeclWriter;
};

/// EnumConstantDecl - An instance of this object exists for each enum constant
/// that is defined.  For example, in "enum X {a,b}", each of a/b are
/// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a
/// TagType for the X EnumDecl.
class EnumConstantDecl : public ValueDecl, public Mergeable<EnumConstantDecl> {
  Stmt *Init; // an integer constant expression
  llvm::APSInt Val; // The value.
protected:
  EnumConstantDecl(DeclContext *DC, SourceLocation L,
                   IdentifierInfo *Id, QualType T, Expr *E,
                   const llvm::APSInt &V)
    : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {}

public:

  static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC,
                                  SourceLocation L, IdentifierInfo *Id,
                                  QualType T, Expr *E,
                                  const llvm::APSInt &V);
  static EnumConstantDecl *CreateDeserialized(ASTContext &C, unsigned ID);
  
  const Expr *getInitExpr() const { return (const Expr*) Init; }
  Expr *getInitExpr() { return (Expr*) Init; }
  const llvm::APSInt &getInitVal() const { return Val; }

  void setInitExpr(Expr *E) { Init = (Stmt*) E; }
  void setInitVal(const llvm::APSInt &V) { Val = V; }

  SourceRange getSourceRange() const override LLVM_READONLY;

  /// Retrieves the canonical declaration of this enumerator.
  EnumConstantDecl *getCanonicalDecl() override { return getFirstDecl(); }
  const EnumConstantDecl *getCanonicalDecl() const { return getFirstDecl(); }

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

  friend class StmtIteratorBase;
};

/// IndirectFieldDecl - An instance of this class is created to represent a
/// field injected from an anonymous union/struct into the parent scope.
/// IndirectFieldDecl are always implicit.
class IndirectFieldDecl : public ValueDecl,
                          public Mergeable<IndirectFieldDecl> {
  void anchor() override;
  NamedDecl **Chaining;
  unsigned ChainingSize;

  IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
                    DeclarationName N, QualType T,
                    MutableArrayRef<NamedDecl *> CH);

public:
  static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC,
                                   SourceLocation L, IdentifierInfo *Id,
                                   QualType T, llvm::MutableArrayRef<NamedDecl *> CH);

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

  typedef ArrayRef<NamedDecl *>::const_iterator chain_iterator;

  ArrayRef<NamedDecl *> chain() const {
    return llvm::makeArrayRef(Chaining, ChainingSize);
  }
  chain_iterator chain_begin() const { return chain().begin(); }
  chain_iterator chain_end() const { return chain().end(); }

  unsigned getChainingSize() const { return ChainingSize; }

  FieldDecl *getAnonField() const {
    assert(chain().size() >= 2);
    return cast<FieldDecl>(chain().back());
  }

  VarDecl *getVarDecl() const {
    assert(chain().size() >= 2);
    return dyn_cast<VarDecl>(chain().front());
  }

  IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); }
  const IndirectFieldDecl *getCanonicalDecl() const { return getFirstDecl(); }

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

/// TypeDecl - Represents a declaration of a type.
///
class TypeDecl : public NamedDecl {
  void anchor() override;
  /// TypeForDecl - This indicates the Type object that represents
  /// this TypeDecl.  It is a cache maintained by
  /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and
  /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl.
  mutable const Type *TypeForDecl;
  /// LocStart - The start of the source range for this declaration.
  SourceLocation LocStart;
  friend class ASTContext;

protected:
  TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
           SourceLocation StartL = SourceLocation())
    : NamedDecl(DK, DC, L, Id), TypeForDecl(nullptr), LocStart(StartL) {}

public:
  // Low-level accessor. If you just want the type defined by this node,
  // check out ASTContext::getTypeDeclType or one of
  // ASTContext::getTypedefType, ASTContext::getRecordType, etc. if you
  // already know the specific kind of node this is.
  const Type *getTypeForDecl() const { return TypeForDecl; }
  void setTypeForDecl(const Type *TD) { TypeForDecl = TD; }

  SourceLocation getLocStart() const LLVM_READONLY { return LocStart; }
  void setLocStart(SourceLocation L) { LocStart = L; }
  SourceRange getSourceRange() const override LLVM_READONLY {
    if (LocStart.isValid())
      return SourceRange(LocStart, getLocation());
    else
      return SourceRange(getLocation());
  }

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


/// Base class for declarations which introduce a typedef-name.
class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
  void anchor() override;
  typedef std::pair<TypeSourceInfo*, QualType> ModedTInfo;
  llvm::PointerUnion<TypeSourceInfo*, ModedTInfo*> MaybeModedTInfo;

  // FIXME: This can be packed into the bitfields in Decl.
  /// If 0, we have not computed IsTransparentTag.
  /// Otherwise, IsTransparentTag is (CacheIsTransparentTag >> 1).
  mutable unsigned CacheIsTransparentTag : 2;

protected:
  TypedefNameDecl(Kind DK, ASTContext &C, DeclContext *DC,
                  SourceLocation StartLoc, SourceLocation IdLoc,
                  IdentifierInfo *Id, TypeSourceInfo *TInfo)
      : TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C),
        MaybeModedTInfo(TInfo), CacheIsTransparentTag(0) {}

  typedef Redeclarable<TypedefNameDecl> redeclarable_base;
  TypedefNameDecl *getNextRedeclarationImpl() override {
    return getNextRedeclaration();
  }
  TypedefNameDecl *getPreviousDeclImpl() override {
    return getPreviousDecl();
  }
  TypedefNameDecl *getMostRecentDeclImpl() override {
    return getMostRecentDecl();
  }

public:
  typedef redeclarable_base::redecl_range redecl_range;
  typedef redeclarable_base::redecl_iterator 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;

  bool isModed() const { return MaybeModedTInfo.is<ModedTInfo*>(); }

  TypeSourceInfo *getTypeSourceInfo() const {
    return isModed()
      ? MaybeModedTInfo.get<ModedTInfo*>()->first
      : MaybeModedTInfo.get<TypeSourceInfo*>();
  }
  QualType getUnderlyingType() const {
    return isModed()
      ? MaybeModedTInfo.get<ModedTInfo*>()->second
      : MaybeModedTInfo.get<TypeSourceInfo*>()->getType();
  }
  void setTypeSourceInfo(TypeSourceInfo *newType) {
    MaybeModedTInfo = newType;
  }
  void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) {
    MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy);
  }

  /// Retrieves the canonical declaration of this typedef-name.
  TypedefNameDecl *getCanonicalDecl() override { return getFirstDecl(); }
  const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); }

  /// Retrieves the tag declaration for which this is the typedef name for
  /// linkage purposes, if any.
  ///
  /// \param AnyRedecl Look for the tag declaration in any redeclaration of
  /// this typedef declaration.
  TagDecl *getAnonDeclWithTypedefName(bool AnyRedecl = false) const;

  /// Determines if this typedef shares a name and spelling location with its
  /// underlying tag type, as is the case with the NS_ENUM macro.
  bool isTransparentTag() const {
    if (CacheIsTransparentTag)
      return CacheIsTransparentTag & 0x2;
    return isTransparentTagSlow();
  }

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

private:
  bool isTransparentTagSlow() const;
};

/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef'
/// type specifier.
class TypedefDecl : public TypedefNameDecl {
  TypedefDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
              SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
      : TypedefNameDecl(Typedef, C, DC, StartLoc, IdLoc, Id, TInfo) {}

public:
  static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
                             SourceLocation StartLoc, SourceLocation IdLoc,
                             IdentifierInfo *Id, TypeSourceInfo *TInfo);
  static TypedefDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  SourceRange getSourceRange() const override LLVM_READONLY;

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

/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x
/// alias-declaration.
class TypeAliasDecl : public TypedefNameDecl {
  /// The template for which this is the pattern, if any.
  TypeAliasTemplateDecl *Template;

  TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
                SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
      : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo),
        Template(nullptr) {}

public:
  static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC,
                               SourceLocation StartLoc, SourceLocation IdLoc,
                               IdentifierInfo *Id, TypeSourceInfo *TInfo);
  static TypeAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  SourceRange getSourceRange() const override LLVM_READONLY;

  TypeAliasTemplateDecl *getDescribedAliasTemplate() const { return Template; }
  void setDescribedAliasTemplate(TypeAliasTemplateDecl *TAT) { Template = TAT; }

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

/// TagDecl - Represents the declaration of a struct/union/class/enum.
class TagDecl
  : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
public:
  // This is really ugly.
  typedef TagTypeKind TagKind;

private:
  // FIXME: This can be packed into the bitfields in Decl.
  /// TagDeclKind - The TagKind enum.
  unsigned TagDeclKind : 3;

  /// IsCompleteDefinition - True if this is a definition ("struct foo
  /// {};"), false if it is a declaration ("struct foo;").  It is not
  /// a definition until the definition has been fully processed.
  unsigned IsCompleteDefinition : 1;

protected:
  /// IsBeingDefined - True if this is currently being defined.
  unsigned IsBeingDefined : 1;

private:
  /// IsEmbeddedInDeclarator - True if this tag declaration is
  /// "embedded" (i.e., defined or declared for the very first time)
  /// in the syntax of a declarator.
  unsigned IsEmbeddedInDeclarator : 1;

  /// \brief True if this tag is free standing, e.g. "struct foo;".
  unsigned IsFreeStanding : 1;

protected:
  // These are used by (and only defined for) EnumDecl.
  unsigned NumPositiveBits : 8;
  unsigned NumNegativeBits : 8;

  /// IsScoped - True if this tag declaration is a scoped enumeration. Only
  /// possible in C++11 mode.
  unsigned IsScoped : 1;
  /// IsScopedUsingClassTag - If this tag declaration is a scoped enum,
  /// then this is true if the scoped enum was declared using the class
  /// tag, false if it was declared with the struct tag. No meaning is
  /// associated if this tag declaration is not a scoped enum.
  unsigned IsScopedUsingClassTag : 1;

  /// IsFixed - True if this is an enumeration with fixed underlying type. Only
  /// possible in C++11, Microsoft extensions, or Objective C mode.
  unsigned IsFixed : 1;

  /// \brief Indicates whether it is possible for declarations of this kind
  /// to have an out-of-date definition.
  ///
  /// This option is only enabled when modules are enabled.
  unsigned MayHaveOutOfDateDef : 1;

  /// Has the full definition of this type been required by a use somewhere in
  /// the TU.
  unsigned IsCompleteDefinitionRequired : 1;
private:
  SourceRange BraceRange;

  // A struct representing syntactic qualifier info,
  // to be used for the (uncommon) case of out-of-line declarations.
  typedef QualifierInfo ExtInfo;

  /// \brief If the (out-of-line) tag declaration name
  /// is qualified, it points to the qualifier info (nns and range);
  /// otherwise, if the tag declaration is anonymous and it is part of
  /// a typedef or alias, it points to the TypedefNameDecl (used for mangling);
  /// otherwise, if the tag declaration is anonymous and it is used as a
  /// declaration specifier for variables, it points to the first VarDecl (used
  /// for mangling);
  /// otherwise, it is a null (TypedefNameDecl) pointer.
  llvm::PointerUnion<TypedefNameDecl *, ExtInfo *> TypedefNameDeclOrQualifier;

  bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo *>(); }
  ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo *>(); }
  const ExtInfo *getExtInfo() const {
    return TypedefNameDeclOrQualifier.get<ExtInfo *>();
  }

protected:
  TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
          SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
          SourceLocation StartL)
      : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C),
        TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false),
        IsEmbeddedInDeclarator(false), IsFreeStanding(false),
        IsCompleteDefinitionRequired(false),
        TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
    assert((DK != Enum || TK == TTK_Enum) &&
           "EnumDecl not matched with TTK_Enum");
    setPreviousDecl(PrevDecl);
  }

  typedef Redeclarable<TagDecl> redeclarable_base;
  TagDecl *getNextRedeclarationImpl() override {
    return getNextRedeclaration();
  }
  TagDecl *getPreviousDeclImpl() override {
    return getPreviousDecl();
  }
  TagDecl *getMostRecentDeclImpl() override {
    return getMostRecentDecl();
  }

  /// @brief Completes the definition of this tag declaration.
  ///
  /// This is a helper function for derived classes.
  void completeDefinition();

public:
  typedef redeclarable_base::redecl_range redecl_range;
  typedef redeclarable_base::redecl_iterator 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;

  SourceRange getBraceRange() const { return BraceRange; }
  void setBraceRange(SourceRange R) { BraceRange = R; }

  /// getInnerLocStart - Return SourceLocation representing start of source
  /// range ignoring outer template declarations.
  SourceLocation getInnerLocStart() const { return getLocStart(); }

  /// getOuterLocStart - Return SourceLocation representing start of source
  /// range taking into account any outer template declarations.
  SourceLocation getOuterLocStart() const;
  SourceRange getSourceRange() const override LLVM_READONLY;

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

  /// isThisDeclarationADefinition() - Return true if this declaration
  /// is a completion definition of the type.  Provided for consistency.
  bool isThisDeclarationADefinition() const {
    return isCompleteDefinition();
  }

  /// isCompleteDefinition - Return true if this decl has its body
  /// fully specified.
  bool isCompleteDefinition() const {
    return IsCompleteDefinition;
  }

  /// \brief Return true if this complete decl is
  /// required to be complete for some existing use.
  bool isCompleteDefinitionRequired() const {
    return IsCompleteDefinitionRequired;
  }

  /// isBeingDefined - Return true if this decl is currently being defined.
  bool isBeingDefined() const {
    return IsBeingDefined;
  }

  bool isEmbeddedInDeclarator() const {
    return IsEmbeddedInDeclarator;
  }
  void setEmbeddedInDeclarator(bool isInDeclarator) {
    IsEmbeddedInDeclarator = isInDeclarator;
  }

  bool isFreeStanding() const { return IsFreeStanding; }
  void setFreeStanding(bool isFreeStanding = true) {
    IsFreeStanding = isFreeStanding;
  }

  /// \brief Whether this declaration declares a type that is
  /// dependent, i.e., a type that somehow depends on template
  /// parameters.
  bool isDependentType() const { return isDependentContext(); }

  /// @brief Starts the definition of this tag declaration.
  ///
  /// This method should be invoked at the beginning of the definition
  /// of this tag declaration. It will set the tag type into a state
  /// where it is in the process of being defined.
  void startDefinition();

  /// getDefinition - Returns the TagDecl that actually defines this
  ///  struct/union/class/enum.  When determining whether or not a
  ///  struct/union/class/enum has a definition, one should use this
  ///  method as opposed to 'isDefinition'.  'isDefinition' indicates
  ///  whether or not a specific TagDecl is defining declaration, not
  ///  whether or not the struct/union/class/enum type is defined.
  ///  This method returns NULL if there is no TagDecl that defines
  ///  the struct/union/class/enum.
  TagDecl *getDefinition() const;

  void setCompleteDefinition(bool V) { IsCompleteDefinition = V; }

  void setCompleteDefinitionRequired(bool V = true) {
    IsCompleteDefinitionRequired = V;
  }

  StringRef getKindName() const {
    return TypeWithKeyword::getTagTypeKindName(getTagKind());
  }

  TagKind getTagKind() const {
    return TagKind(TagDeclKind);
  }

  void setTagKind(TagKind TK) { TagDeclKind = TK; }

  bool isStruct() const { return getTagKind() == TTK_Struct; }
  bool isInterface() const { return getTagKind() == TTK_Interface; }
  bool isClass()  const { return getTagKind() == TTK_Class; }
  bool isUnion()  const { return getTagKind() == TTK_Union; }
  bool isEnum()   const { return getTagKind() == TTK_Enum; }

  /// Is this tag type named, either directly or via being defined in
  /// a typedef of this type?
  ///
  /// C++11 [basic.link]p8:
  ///   A type is said to have linkage if and only if:
  ///     - it is a class or enumeration type that is named (or has a
  ///       name for linkage purposes) and the name has linkage; ...
  /// C++11 [dcl.typedef]p9:
  ///   If the typedef declaration defines an unnamed class (or enum),
  ///   the first typedef-name declared by the declaration to be that
  ///   class type (or enum type) is used to denote the class type (or
  ///   enum type) for linkage purposes only.
  ///
  /// C does not have an analogous rule, but the same concept is
  /// nonetheless useful in some places.
  bool hasNameForLinkage() const {
    return (getDeclName() || getTypedefNameForAnonDecl());
  }

  TypedefNameDecl *getTypedefNameForAnonDecl() const {
    return hasExtInfo() ? nullptr
                        : TypedefNameDeclOrQualifier.get<TypedefNameDecl *>();
  }

  void setTypedefNameForAnonDecl(TypedefNameDecl *TDD);

  /// \brief Retrieve the nested-name-specifier that qualifies the name of this
  /// declaration, if it was present in the source.
  NestedNameSpecifier *getQualifier() const {
    return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
                        : nullptr;
  }

  /// \brief Retrieve the nested-name-specifier (with source-location
  /// information) that qualifies the name of this declaration, if it was
  /// present in the source.
  NestedNameSpecifierLoc getQualifierLoc() const {
    return hasExtInfo() ? getExtInfo()->QualifierLoc
                        : NestedNameSpecifierLoc();
  }

  void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);

  unsigned getNumTemplateParameterLists() const {
    return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
  }
  TemplateParameterList *getTemplateParameterList(unsigned i) const {
    assert(i < getNumTemplateParameterLists());
    return getExtInfo()->TemplParamLists[i];
  }
  void setTemplateParameterListsInfo(ASTContext &Context,
                                     ArrayRef<TemplateParameterList *> TPLists);

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

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

  friend class ASTDeclReader;
  friend class ASTDeclWriter;
};

/// EnumDecl - Represents an enum.  In C++11, enums can be forward-declared
/// with a fixed underlying type, and in C we allow them to be forward-declared
/// with no underlying type as an extension.
class EnumDecl : public TagDecl {
  void anchor() override;
  /// IntegerType - This represent the integer type that the enum corresponds
  /// to for code generation purposes.  Note that the enumerator constants may
  /// have a different type than this does.
  ///
  /// If the underlying integer type was explicitly stated in the source
  /// code, this is a TypeSourceInfo* for that type. Otherwise this type
  /// was automatically deduced somehow, and this is a Type*.
  ///
  /// Normally if IsFixed(), this would contain a TypeSourceInfo*, but in
  /// some cases it won't.
  ///
  /// The underlying type of an enumeration never has any qualifiers, so
  /// we can get away with just storing a raw Type*, and thus save an
  /// extra pointer when TypeSourceInfo is needed.

  llvm::PointerUnion<const Type*, TypeSourceInfo*> IntegerType;

  /// PromotionType - The integer type that values of this type should
  /// promote to.  In C, enumerators are generally of an integer type
  /// directly, but gcc-style large enumerators (and all enumerators
  /// in C++) are of the enum type instead.
  QualType PromotionType;

  /// \brief If this enumeration is an instantiation of a member enumeration
  /// of a class template specialization, this is the member specialization
  /// information.
  MemberSpecializationInfo *SpecializationInfo;

  EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
           SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
           bool Scoped, bool ScopedUsingClassTag, bool Fixed)
      : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc),
        SpecializationInfo(nullptr) {
    assert(Scoped || !ScopedUsingClassTag);
    IntegerType = (const Type *)nullptr;
    NumNegativeBits = 0;
    NumPositiveBits = 0;
    IsScoped = Scoped;
    IsScopedUsingClassTag = ScopedUsingClassTag;
    IsFixed = Fixed;
  }

  void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
                                    TemplateSpecializationKind TSK);
public:
  EnumDecl *getCanonicalDecl() override {
    return cast<EnumDecl>(TagDecl::getCanonicalDecl());
  }
  const EnumDecl *getCanonicalDecl() const {
    return const_cast<EnumDecl*>(this)->getCanonicalDecl();
  }

  EnumDecl *getPreviousDecl() {
    return cast_or_null<EnumDecl>(
            static_cast<TagDecl *>(this)->getPreviousDecl());
  }
  const EnumDecl *getPreviousDecl() const {
    return const_cast<EnumDecl*>(this)->getPreviousDecl();
  }

  EnumDecl *getMostRecentDecl() {
    return cast<EnumDecl>(static_cast<TagDecl *>(this)->getMostRecentDecl());
  }
  const EnumDecl *getMostRecentDecl() const {
    return const_cast<EnumDecl*>(this)->getMostRecentDecl();
  }

  EnumDecl *getDefinition() const {
    return cast_or_null<EnumDecl>(TagDecl::getDefinition());
  }

  static EnumDecl *Create(ASTContext &C, DeclContext *DC,
                          SourceLocation StartLoc, SourceLocation IdLoc,
                          IdentifierInfo *Id, EnumDecl *PrevDecl,
                          bool IsScoped, bool IsScopedUsingClassTag,
                          bool IsFixed);
  static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID);

  /// completeDefinition - When created, the EnumDecl corresponds to a
  /// forward-declared enum. This method is used to mark the
  /// declaration as being defined; it's enumerators have already been
  /// added (via DeclContext::addDecl). NewType is the new underlying
  /// type of the enumeration type.
  void completeDefinition(QualType NewType,
                          QualType PromotionType,
                          unsigned NumPositiveBits,
                          unsigned NumNegativeBits);

  // enumerator_iterator - Iterates through the enumerators of this
  // enumeration.
  typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator;
  typedef llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>>
    enumerator_range;

  enumerator_range enumerators() const {
    return enumerator_range(enumerator_begin(), enumerator_end());
  }

  enumerator_iterator enumerator_begin() const {
    const EnumDecl *E = getDefinition();
    if (!E)
      E = this;
    return enumerator_iterator(E->decls_begin());
  }

  enumerator_iterator enumerator_end() const {
    const EnumDecl *E = getDefinition();
    if (!E)
      E = this;
    return enumerator_iterator(E->decls_end());
  }

  /// getPromotionType - Return the integer type that enumerators
  /// should promote to.
  QualType getPromotionType() const { return PromotionType; }

  /// \brief Set the promotion type.
  void setPromotionType(QualType T) { PromotionType = T; }

  /// getIntegerType - Return the integer type this enum decl corresponds to.
  /// This returns a null QualType for an enum forward definition with no fixed
  /// underlying type.
  QualType getIntegerType() const {
    if (!IntegerType)
      return QualType();
    if (const Type *T = IntegerType.dyn_cast<const Type*>())
      return QualType(T, 0);
    return IntegerType.get<TypeSourceInfo*>()->getType().getUnqualifiedType();
  }

  /// \brief Set the underlying integer type.
  void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); }

  /// \brief Set the underlying integer type source info.
  void setIntegerTypeSourceInfo(TypeSourceInfo *TInfo) { IntegerType = TInfo; }

  /// \brief Return the type source info for the underlying integer type,
  /// if no type source info exists, return 0.
  TypeSourceInfo *getIntegerTypeSourceInfo() const {
    return IntegerType.dyn_cast<TypeSourceInfo*>();
  }

  /// \brief Retrieve the source range that covers the underlying type if
  /// specified.
  SourceRange getIntegerTypeRange() const LLVM_READONLY;

  /// \brief Returns the width in bits required to store all the
  /// non-negative enumerators of this enum.
  unsigned getNumPositiveBits() const {
    return NumPositiveBits;
  }
  void setNumPositiveBits(unsigned Num) {
    NumPositiveBits = Num;
    assert(NumPositiveBits == Num && "can't store this bitcount");
  }

  /// \brief Returns the width in bits required to store all the
  /// negative enumerators of this enum.  These widths include
  /// the rightmost leading 1;  that is:
  ///
  /// MOST NEGATIVE ENUMERATOR     PATTERN     NUM NEGATIVE BITS
  /// ------------------------     -------     -----------------
  ///                       -1     1111111                     1
  ///                      -10     1110110                     5
  ///                     -101     1001011                     8
  unsigned getNumNegativeBits() const {
    return NumNegativeBits;
  }
  void setNumNegativeBits(unsigned Num) {
    NumNegativeBits = Num;
  }

  /// \brief Returns true if this is a C++11 scoped enumeration.
  bool isScoped() const {
    return IsScoped;
  }

  /// \brief Returns true if this is a C++11 scoped enumeration.
  bool isScopedUsingClassTag() const {
    return IsScopedUsingClassTag;
  }

  /// \brief Returns true if this is an Objective-C, C++11, or
  /// Microsoft-style enumeration with a fixed underlying type.
  bool isFixed() const {
    return IsFixed;
  }

  /// \brief Returns true if this can be considered a complete type.
  bool isComplete() const {
    return isCompleteDefinition() || isFixed();
  }

  /// Returns true if this enum is either annotated with
  /// enum_extensibility(closed) or isn't annotated with enum_extensibility.
  bool isClosed() const;

  /// Returns true if this enum is annotated with flag_enum and isn't annotated
  /// with enum_extensibility(open).
  bool isClosedFlag() const;

  /// Returns true if this enum is annotated with neither flag_enum nor
  /// enum_extensibility(open).
  bool isClosedNonFlag() const;

  /// \brief Retrieve the enum definition from which this enumeration could
  /// be instantiated, if it is an instantiation (rather than a non-template).
  EnumDecl *getTemplateInstantiationPattern() const;

  /// \brief Returns the enumeration (declared within the template)
  /// from which this enumeration type was instantiated, or NULL if
  /// this enumeration was not instantiated from any template.
  EnumDecl *getInstantiatedFromMemberEnum() const;

  /// \brief If this enumeration is a member of a specialization of a
  /// templated class, determine what kind of template specialization
  /// or instantiation this is.
  TemplateSpecializationKind getTemplateSpecializationKind() const;

  /// \brief For an enumeration member that was instantiated from a member
  /// enumeration of a templated class, set the template specialiation kind.
  void setTemplateSpecializationKind(TemplateSpecializationKind TSK,
                        SourceLocation PointOfInstantiation = SourceLocation());

  /// \brief If this enumeration is an instantiation of a member enumeration of
  /// a class template specialization, retrieves the member specialization
  /// information.
  MemberSpecializationInfo *getMemberSpecializationInfo() const {
    return SpecializationInfo;
  }

  /// \brief Specify that this enumeration is an instantiation of the
  /// member enumeration ED.
  void setInstantiationOfMemberEnum(EnumDecl *ED,
                                    TemplateSpecializationKind TSK) {
    setInstantiationOfMemberEnum(getASTContext(), ED, TSK);
  }

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

  friend class ASTDeclReader;
};


/// RecordDecl - Represents a struct/union/class.  For example:
///   struct X;                  // Forward declaration, no "body".
///   union Y { int A, B; };     // Has body with members A and B (FieldDecls).
/// This decl will be marked invalid if *any* members are invalid.
///
class RecordDecl : public TagDecl {
  // FIXME: This can be packed into the bitfields in Decl.
  /// HasFlexibleArrayMember - This is true if this struct ends with a flexible
  /// array member (e.g. int X[]) or if this union contains a struct that does.
  /// If so, this cannot be contained in arrays or other structs as a member.
  bool HasFlexibleArrayMember : 1;

  /// AnonymousStructOrUnion - Whether this is the type of an anonymous struct
  /// or union.
  bool AnonymousStructOrUnion : 1;

  /// HasObjectMember - This is true if this struct has at least one member
  /// containing an Objective-C object pointer type.
  bool HasObjectMember : 1;
  
  /// HasVolatileMember - This is true if struct has at least one member of
  /// 'volatile' type.
  bool HasVolatileMember : 1;

  /// \brief Whether the field declarations of this record have been loaded
  /// from external storage. To avoid unnecessary deserialization of
  /// methods/nested types we allow deserialization of just the fields
  /// when needed.
  mutable bool LoadedFieldsFromExternalStorage : 1;
  friend class DeclContext;

protected:
  RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
             SourceLocation StartLoc, SourceLocation IdLoc,
             IdentifierInfo *Id, RecordDecl *PrevDecl);

public:
  static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC,
                            SourceLocation StartLoc, SourceLocation IdLoc,
                            IdentifierInfo *Id, RecordDecl* PrevDecl = nullptr);
  static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID);

  RecordDecl *getPreviousDecl() {
    return cast_or_null<RecordDecl>(
            static_cast<TagDecl *>(this)->getPreviousDecl());
  }
  const RecordDecl *getPreviousDecl() const {
    return const_cast<RecordDecl*>(this)->getPreviousDecl();
  }

  RecordDecl *getMostRecentDecl() {
    return cast<RecordDecl>(static_cast<TagDecl *>(this)->getMostRecentDecl());
  }
  const RecordDecl *getMostRecentDecl() const {
    return const_cast<RecordDecl*>(this)->getMostRecentDecl();
  }

  bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
  void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }

  /// isAnonymousStructOrUnion - Whether this is an anonymous struct
  /// or union. To be an anonymous struct or union, it must have been
  /// declared without a name and there must be no objects of this
  /// type declared, e.g.,
  /// @code
  ///   union { int i; float f; };
  /// @endcode
  /// is an anonymous union but neither of the following are:
  /// @code
  ///  union X { int i; float f; };
  ///  union { int i; float f; } obj;
  /// @endcode
  bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; }
  void setAnonymousStructOrUnion(bool Anon) {
    AnonymousStructOrUnion = Anon;
  }

  bool hasObjectMember() const { return HasObjectMember; }
  void setHasObjectMember (bool val) { HasObjectMember = val; }

  bool hasVolatileMember() const { return HasVolatileMember; }
  void setHasVolatileMember (bool val) { HasVolatileMember = val; }

  bool hasLoadedFieldsFromExternalStorage() const {
    return LoadedFieldsFromExternalStorage;
  }
  void setHasLoadedFieldsFromExternalStorage(bool val) {
    LoadedFieldsFromExternalStorage = val;
  }

  /// \brief Determines whether this declaration represents the
  /// injected class name.
  ///
  /// The injected class name in C++ is the name of the class that
  /// appears inside the class itself. For example:
  ///
  /// \code
  /// struct C {
  ///   // C is implicitly declared here as a synonym for the class name.
  /// };
  ///
  /// C::C c; // same as "C c;"
  /// \endcode
  bool isInjectedClassName() const;

  /// \brief Determine whether this record is a class describing a lambda
  /// function object.
  bool isLambda() const;

  /// \brief Determine whether this record is a record for captured variables in
  /// CapturedStmt construct.
  bool isCapturedRecord() const;
  /// \brief Mark the record as a record for captured variables in CapturedStmt
  /// construct.
  void setCapturedRecord();

  /// getDefinition - Returns the RecordDecl that actually defines
  ///  this struct/union/class.  When determining whether or not a
  ///  struct/union/class is completely defined, one should use this
  ///  method as opposed to 'isCompleteDefinition'.
  ///  'isCompleteDefinition' indicates whether or not a specific
  ///  RecordDecl is a completed definition, not whether or not the
  ///  record type is defined.  This method returns NULL if there is
  ///  no RecordDecl that defines the struct/union/tag.
  RecordDecl *getDefinition() const {
    return cast_or_null<RecordDecl>(TagDecl::getDefinition());
  }

  // Iterator access to field members. The field iterator only visits
  // the non-static data members of this class, ignoring any static
  // data members, functions, constructors, destructors, etc.
  typedef specific_decl_iterator<FieldDecl> field_iterator;
  typedef llvm::iterator_range<specific_decl_iterator<FieldDecl>> field_range;

  field_range fields() const { return field_range(field_begin(), field_end()); }
  field_iterator field_begin() const;

  field_iterator field_end() const {
    return field_iterator(decl_iterator());
  }

  // field_empty - Whether there are any fields (non-static data
  // members) in this record.
  bool field_empty() const {
    return field_begin() == field_end();
  }

  /// completeDefinition - Notes that the definition of this type is
  /// now complete.
  virtual void completeDefinition();

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

  /// isMsStrust - Get whether or not this is an ms_struct which can
  /// be turned on with an attribute, pragma, or -mms-bitfields
  /// commandline option.
  bool isMsStruct(const ASTContext &C) const;

  /// \brief Whether we are allowed to insert extra padding between fields.
  /// These padding are added to help AddressSanitizer detect
  /// intra-object-overflow bugs.
  bool mayInsertExtraPadding(bool EmitRemark = false) const;

  /// Finds the first data member which has a name.
  /// nullptr is returned if no named data member exists.
  const FieldDecl *findFirstNamedDataMember() const;  

private:
  /// \brief Deserialize just the fields.
  void LoadFieldsFromExternalStorage() const;
};

class FileScopeAsmDecl : public Decl {
  virtual void anchor();
  StringLiteral *AsmString;
  SourceLocation RParenLoc;
  FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring,
                   SourceLocation StartL, SourceLocation EndL)
    : Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {}
public:
  static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC,
                                  StringLiteral *Str, SourceLocation AsmLoc,
                                  SourceLocation RParenLoc);

  static FileScopeAsmDecl *CreateDeserialized(ASTContext &C, unsigned ID);
  
  SourceLocation getAsmLoc() const { return getLocation(); }
  SourceLocation getRParenLoc() const { return RParenLoc; }
  void setRParenLoc(SourceLocation L) { RParenLoc = L; }
  SourceRange getSourceRange() const override LLVM_READONLY {
    return SourceRange(getAsmLoc(), getRParenLoc());
  }

  const StringLiteral *getAsmString() const { return AsmString; }
  StringLiteral *getAsmString() { return AsmString; }
  void setAsmString(StringLiteral *Asm) { AsmString = Asm; }

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

/// BlockDecl - This represents a block literal declaration, which is like an
/// unnamed FunctionDecl.  For example:
/// ^{ statement-body }   or   ^(int arg1, float arg2){ statement-body }
///
class BlockDecl : public Decl, public DeclContext {
public:
  /// A class which contains all the information about a particular
  /// captured value.
  class Capture {
    enum {
      flag_isByRef = 0x1,
      flag_isNested = 0x2
    };

    /// The variable being captured.
    llvm::PointerIntPair<VarDecl*, 2> VariableAndFlags;

    /// The copy expression, expressed in terms of a DeclRef (or
    /// BlockDeclRef) to the captured variable.  Only required if the
    /// variable has a C++ class type.
    Expr *CopyExpr;

  public:
    Capture(VarDecl *variable, bool byRef, bool nested, Expr *copy)
      : VariableAndFlags(variable,
                  (byRef ? flag_isByRef : 0) | (nested ? flag_isNested : 0)),
        CopyExpr(copy) {}

    /// The variable being captured.
    VarDecl *getVariable() const { return VariableAndFlags.getPointer(); }

    /// Whether this is a "by ref" capture, i.e. a capture of a __block
    /// variable.
    bool isByRef() const { return VariableAndFlags.getInt() & flag_isByRef; }

    /// Whether this is a nested capture, i.e. the variable captured
    /// is not from outside the immediately enclosing function/block.
    bool isNested() const { return VariableAndFlags.getInt() & flag_isNested; }

    bool hasCopyExpr() const { return CopyExpr != nullptr; }
    Expr *getCopyExpr() const { return CopyExpr; }
    void setCopyExpr(Expr *e) { CopyExpr = e; }
  };

private:
  // FIXME: This can be packed into the bitfields in Decl.
  bool IsVariadic : 1;
  bool CapturesCXXThis : 1;
  bool BlockMissingReturnType : 1;
  bool IsConversionFromLambda : 1;
  /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal
  /// parameters of this function.  This is null if a prototype or if there are
  /// no formals.
  ParmVarDecl **ParamInfo;
  unsigned NumParams;

  Stmt *Body;
  TypeSourceInfo *SignatureAsWritten;

  const Capture *Captures;
  unsigned NumCaptures;

  unsigned ManglingNumber;
  Decl *ManglingContextDecl;

protected:
  BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
    : Decl(Block, DC, CaretLoc), DeclContext(Block),
      IsVariadic(false), CapturesCXXThis(false),
      BlockMissingReturnType(true), IsConversionFromLambda(false),
      ParamInfo(nullptr), NumParams(0), Body(nullptr),
      SignatureAsWritten(nullptr), Captures(nullptr), NumCaptures(0),
      ManglingNumber(0), ManglingContextDecl(nullptr) {}

public:
  static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); 
  static BlockDecl *CreateDeserialized(ASTContext &C, unsigned ID);
  
  SourceLocation getCaretLocation() const { return getLocation(); }

  bool isVariadic() const { return IsVariadic; }
  void setIsVariadic(bool value) { IsVariadic = value; }

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

  void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; }
  TypeSourceInfo *getSignatureAsWritten() const { return SignatureAsWritten; }

  // ArrayRef access to formal parameters.
  ArrayRef<ParmVarDecl *> parameters() const {
    return {ParamInfo, getNumParams()};
  }
  MutableArrayRef<ParmVarDecl *> parameters() {
    return {ParamInfo, getNumParams()};
  }

  // Iterator access to formal parameters.
  typedef MutableArrayRef<ParmVarDecl *>::iterator param_iterator;
  typedef ArrayRef<ParmVarDecl *>::const_iterator param_const_iterator;
  bool param_empty() const { return parameters().empty(); }
  param_iterator param_begin() { return parameters().begin(); }
  param_iterator param_end() { return parameters().end(); }
  param_const_iterator param_begin() const { return parameters().begin(); }
  param_const_iterator param_end() const { return parameters().end(); }
  size_t param_size() const { return parameters().size(); }

  unsigned getNumParams() const { return NumParams; }
  const ParmVarDecl *getParamDecl(unsigned i) const {
    assert(i < getNumParams() && "Illegal param #");
    return ParamInfo[i];
  }
  ParmVarDecl *getParamDecl(unsigned i) {
    assert(i < getNumParams() && "Illegal param #");
    return ParamInfo[i];
  }
  void setParams(ArrayRef<ParmVarDecl *> NewParamInfo);

  /// hasCaptures - True if this block (or its nested blocks) captures
  /// anything of local storage from its enclosing scopes.
  bool hasCaptures() const { return NumCaptures != 0 || CapturesCXXThis; }

  /// getNumCaptures - Returns the number of captured variables.
  /// Does not include an entry for 'this'.
  unsigned getNumCaptures() const { return NumCaptures; }

  typedef ArrayRef<Capture>::const_iterator capture_const_iterator;

  ArrayRef<Capture> captures() const { return {Captures, NumCaptures}; }

  capture_const_iterator capture_begin() const { return captures().begin(); }
  capture_const_iterator capture_end() const { return captures().end(); }

  bool capturesCXXThis() const { return CapturesCXXThis; }
  bool blockMissingReturnType() const { return BlockMissingReturnType; }
  void setBlockMissingReturnType(bool val) { BlockMissingReturnType = val; }

  bool isConversionFromLambda() const { return IsConversionFromLambda; }
  void setIsConversionFromLambda(bool val) { IsConversionFromLambda = val; }

  bool capturesVariable(const VarDecl *var) const;

  void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
                   bool CapturesCXXThis);

   unsigned getBlockManglingNumber() const {
     return ManglingNumber;
   }
   Decl *getBlockManglingContextDecl() const {
     return ManglingContextDecl;    
   }

  void setBlockMangling(unsigned Number, Decl *Ctx) {
    ManglingNumber = Number;
    ManglingContextDecl = Ctx;
  }

  SourceRange getSourceRange() const override LLVM_READONLY;

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == Block; }
  static DeclContext *castToDeclContext(const BlockDecl *D) {
    return static_cast<DeclContext *>(const_cast<BlockDecl*>(D));
  }
  static BlockDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<BlockDecl *>(const_cast<DeclContext*>(DC));
  }
};

/// \brief This represents the body of a CapturedStmt, and serves as its
/// DeclContext.
class CapturedDecl final
    : public Decl,
      public DeclContext,
      private llvm::TrailingObjects<CapturedDecl, ImplicitParamDecl *> {
protected:
  size_t numTrailingObjects(OverloadToken<ImplicitParamDecl>) {
    return NumParams;
  }

private:
  /// \brief The number of parameters to the outlined function.
  unsigned NumParams;
  /// \brief The position of context parameter in list of parameters.
  unsigned ContextParam;
  /// \brief The body of the outlined function.
  llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow;

  explicit CapturedDecl(DeclContext *DC, unsigned NumParams);

  ImplicitParamDecl *const *getParams() const {
    return getTrailingObjects<ImplicitParamDecl *>();
  }

  ImplicitParamDecl **getParams() {
    return getTrailingObjects<ImplicitParamDecl *>();
  }

public:
  static CapturedDecl *Create(ASTContext &C, DeclContext *DC,
                              unsigned NumParams);
  static CapturedDecl *CreateDeserialized(ASTContext &C, unsigned ID,
                                          unsigned NumParams);

  Stmt *getBody() const override;
  void setBody(Stmt *B);

  bool isNothrow() const;
  void setNothrow(bool Nothrow = true);

  unsigned getNumParams() const { return NumParams; }

  ImplicitParamDecl *getParam(unsigned i) const {
    assert(i < NumParams);
    return getParams()[i];
  }
  void setParam(unsigned i, ImplicitParamDecl *P) {
    assert(i < NumParams);
    getParams()[i] = P;
  }

  // ArrayRef interface to parameters.
  ArrayRef<ImplicitParamDecl *> parameters() const {
    return {getParams(), getNumParams()};
  }
  MutableArrayRef<ImplicitParamDecl *> parameters() {
    return {getParams(), getNumParams()};
  }

  /// \brief Retrieve the parameter containing captured variables.
  ImplicitParamDecl *getContextParam() const {
    assert(ContextParam < NumParams);
    return getParam(ContextParam);
  }
  void setContextParam(unsigned i, ImplicitParamDecl *P) {
    assert(i < NumParams);
    ContextParam = i;
    setParam(i, P);
  }
  unsigned getContextParamPosition() const { return ContextParam; }

  typedef ImplicitParamDecl *const *param_iterator;
  typedef llvm::iterator_range<param_iterator> param_range;

  /// \brief Retrieve an iterator pointing to the first parameter decl.
  param_iterator param_begin() const { return getParams(); }
  /// \brief Retrieve an iterator one past the last parameter decl.
  param_iterator param_end() const { return getParams() + NumParams; }

  // Implement isa/cast/dyncast/etc.
  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == Captured; }
  static DeclContext *castToDeclContext(const CapturedDecl *D) {
    return static_cast<DeclContext *>(const_cast<CapturedDecl *>(D));
  }
  static CapturedDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<CapturedDecl *>(const_cast<DeclContext *>(DC));
  }

  friend class ASTDeclReader;
  friend class ASTDeclWriter;
  friend TrailingObjects;
};

/// \brief Describes a module import declaration, which makes the contents
/// of the named module visible in the current translation unit.
///
/// An import declaration imports the named module (or submodule). For example:
/// \code
///   @import std.vector;
/// \endcode
///
/// Import declarations can also be implicitly generated from
/// \#include/\#import directives.
class ImportDecl final : public Decl,
                         llvm::TrailingObjects<ImportDecl, SourceLocation> {
  /// \brief The imported module, along with a bit that indicates whether
  /// we have source-location information for each identifier in the module
  /// name. 
  ///
  /// When the bit is false, we only have a single source location for the
  /// end of the import declaration.
  llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete;
  
  /// \brief The next import in the list of imports local to the translation
  /// unit being parsed (not loaded from an AST file).
  ImportDecl *NextLocalImport;
  
  friend class ASTReader;
  friend class ASTDeclReader;
  friend class ASTContext;
  friend TrailingObjects;

  ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
             ArrayRef<SourceLocation> IdentifierLocs);

  ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
             SourceLocation EndLoc);

  ImportDecl(EmptyShell Empty) : Decl(Import, Empty), NextLocalImport() { }
  
public:
  /// \brief Create a new module import declaration.
  static ImportDecl *Create(ASTContext &C, DeclContext *DC, 
                            SourceLocation StartLoc, Module *Imported,
                            ArrayRef<SourceLocation> IdentifierLocs);
  
  /// \brief Create a new module import declaration for an implicitly-generated
  /// import.
  static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC, 
                                    SourceLocation StartLoc, Module *Imported, 
                                    SourceLocation EndLoc);
  
  /// \brief Create a new, deserialized module import declaration.
  static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID, 
                                        unsigned NumLocations);
  
  /// \brief Retrieve the module that was imported by the import declaration.
  Module *getImportedModule() const { return ImportedAndComplete.getPointer(); }
  
  /// \brief Retrieves the locations of each of the identifiers that make up
  /// the complete module name in the import declaration.
  ///
  /// This will return an empty array if the locations of the individual
  /// identifiers aren't available.
  ArrayRef<SourceLocation> getIdentifierLocs() const;

  SourceRange getSourceRange() const override LLVM_READONLY;

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

/// \brief Represents a C++ Modules TS module export declaration.
///
/// For example:
/// \code
///   export void foo();
/// \endcode
class ExportDecl final : public Decl, public DeclContext {
  virtual void anchor();
private:
  /// \brief The source location for the right brace (if valid).
  SourceLocation RBraceLoc;

  ExportDecl(DeclContext *DC, SourceLocation ExportLoc)
    : Decl(Export, DC, ExportLoc), DeclContext(Export),
      RBraceLoc(SourceLocation()) { }

  friend class ASTDeclReader;

public:
  static ExportDecl *Create(ASTContext &C, DeclContext *DC,
                            SourceLocation ExportLoc);
  static ExportDecl *CreateDeserialized(ASTContext &C, unsigned ID);
  
  SourceLocation getExportLoc() const { return getLocation(); }
  SourceLocation getRBraceLoc() const { return RBraceLoc; }
  void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }

  SourceLocation getLocEnd() const LLVM_READONLY {
    if (RBraceLoc.isValid())
      return RBraceLoc;
    // No braces: get the end location of the (only) declaration in context
    // (if present).
    return decls_empty() ? getLocation() : decls_begin()->getLocEnd();
  }

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

  static bool classof(const Decl *D) { return classofKind(D->getKind()); }
  static bool classofKind(Kind K) { return K == Export; }
  static DeclContext *castToDeclContext(const ExportDecl *D) {
    return static_cast<DeclContext *>(const_cast<ExportDecl*>(D));
  }
  static ExportDecl *castFromDeclContext(const DeclContext *DC) {
    return static_cast<ExportDecl *>(const_cast<DeclContext*>(DC));
  }
};

/// \brief Represents an empty-declaration.
class EmptyDecl : public Decl {
  virtual void anchor();
  EmptyDecl(DeclContext *DC, SourceLocation L)
    : Decl(Empty, DC, L) { }

public:
  static EmptyDecl *Create(ASTContext &C, DeclContext *DC,
                           SourceLocation L);
  static EmptyDecl *CreateDeserialized(ASTContext &C, unsigned ID);

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

/// Insertion operator for diagnostics.  This allows sending NamedDecl's
/// into a diagnostic with <<.
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
                                           const NamedDecl* ND) {
  DB.AddTaggedVal(reinterpret_cast<intptr_t>(ND),
                  DiagnosticsEngine::ak_nameddecl);
  return DB;
}
inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
                                           const NamedDecl* ND) {
  PD.AddTaggedVal(reinterpret_cast<intptr_t>(ND),
                  DiagnosticsEngine::ak_nameddecl);
  return PD;
}

template<typename decl_type>
void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) {
  // Note: This routine is implemented here because we need both NamedDecl
  // and Redeclarable to be defined.
  assert(RedeclLink.NextIsLatest() &&
         "setPreviousDecl on a decl already in a redeclaration chain");

  if (PrevDecl) {
    // Point to previous. Make sure that this is actually the most recent
    // redeclaration, or we can build invalid chains. If the most recent
    // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
    First = PrevDecl->getFirstDecl();
    assert(First->RedeclLink.NextIsLatest() && "Expected first");
    decl_type *MostRecent = First->getNextRedeclaration();
    RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent));

    // If the declaration was previously visible, a redeclaration of it remains
    // visible even if it wouldn't be visible by itself.
    static_cast<decl_type*>(this)->IdentifierNamespace |=
      MostRecent->getIdentifierNamespace() &
      (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
  } else {
    // Make this first.
    First = static_cast<decl_type*>(this);
  }

  // First one will point to this one as latest.
  First->RedeclLink.setLatest(static_cast<decl_type*>(this));

  assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) ||
         cast<NamedDecl>(static_cast<decl_type*>(this))->isLinkageValid());
}

// Inline function definitions.

/// \brief Check if the given decl is complete.
///
/// We use this function to break a cycle between the inline definitions in
/// Type.h and Decl.h.
inline bool IsEnumDeclComplete(EnumDecl *ED) {
  return ED->isComplete();
}

/// \brief Check if the given decl is scoped.
///
/// We use this function to break a cycle between the inline definitions in
/// Type.h and Decl.h.
inline bool IsEnumDeclScoped(EnumDecl *ED) {
  return ED->isScoped();
}

}  // end namespace clang

#endif
