//===- Decl.h - Classes for representing declarations -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines the Decl subclasses.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_DECL_H
#define LLVM_CLANG_AST_DECL_H

#include "clang/AST/APValue.h"
#include "clang/AST/ASTContextAllocate.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/Visibility.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <string>
#include <utility>

namespace clang {

class ASTContext;
struct ASTTemplateArgumentListInfo;
class CompoundStmt;
class DependentFunctionTemplateSpecializationInfo;
class EnumDecl;
class Expr;
class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class FunctionTypeLoc;
class LabelStmt;
class MemberSpecializationInfo;
class Module;
class NamespaceDecl;
class ParmVarDecl;
class RecordDecl;
class Stmt;
class StringLiteral;
class TagDecl;
class TemplateArgumentList;
class TemplateArgumentListInfo;
class TemplateParameterList;
class TypeAliasTemplateDecl;
class UnresolvedSetImpl;
class VarTemplateDecl;

/// The top declaration context.
class TranslationUnitDecl : public Decl,
                            public DeclContext,
                            public Redeclarable<TranslationUnitDecl> {
  using redeclarable_base = Redeclarable<TranslationUnitDecl>;

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

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

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

  ASTContext &Ctx;

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

  explicit TranslationUnitDecl(ASTContext &ctx);

  virtual void anchor();

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

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

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

/// Represents a `#pragma comment` line. Always a child of
/// TranslationUnitDecl.
class PragmaCommentDecl final
    : public Decl,
      private llvm::TrailingObjects<PragmaCommentDecl, char> {
  friend class ASTDeclReader;
  friend class ASTDeclWriter;
  friend TrailingObjects;

  PragmaMSCommentKind CommentKind;

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

  virtual void anchor();

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

/// Represents a `#pragma detect_mismatch` line. Always a child of
/// TranslationUnitDecl.
class PragmaDetectMismatchDecl final
    : public Decl,
      private llvm::TrailingObjects<PragmaDetectMismatchDecl, char> {
  friend class ASTDeclReader;
  friend class ASTDeclWriter;
  friend TrailingObjects;

  size_t ValueStart;

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

  virtual void anchor();

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

/// 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 {
  explicit ExternCContextDecl(TranslationUnitDecl *TU)
    : Decl(ExternCContext, TU, SourceLocation()),
      DeclContext(ExternCContext) {}

  virtual void anchor();

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

/// This represents a decl that may have a name.  Many decls have names such
/// as ObjCMethodDecl, but not \@class, etc.
///
/// Note that not every NamedDecl is actually named (e.g., a struct might
/// be anonymous), and not every name is an identifier.
class NamedDecl : public Decl {
  /// 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;

  virtual void anchor();

private:
  NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY;

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

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

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

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

  /// Pretty-print the unqualified name of this declaration. Can be overloaded
  /// by derived classes to provide a more user-friendly name when appropriate.
  virtual void printName(raw_ostream &os) const;

  /// Get the actual, stored name of the declaration, which may be a special
  /// name.
  ///
  /// Note that generally in diagnostics, the non-null \p NamedDecl* itself
  /// should be sent into the diagnostic instead of using the result of
  /// \p getDeclName().
  ///
  /// A \p DeclarationName in a diagnostic will just be streamed to the output,
  /// which will directly result in a call to \p DeclarationName::print.
  ///
  /// A \p NamedDecl* in a diagnostic will also ultimately result in a call to
  /// \p DeclarationName::print, but with two customisation points along the
  /// way (\p getNameForDiagnostic and \p printName). These are used to print
  /// the template arguments if any, and to provide a user-friendly name for
  /// some entities (such as unnamed variables and anonymous records).
  DeclarationName getDeclName() const { return Name; }

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

  /// Returns a human-readable qualified name for this declaration, like
  /// A::B::i, for i being member of namespace A::B.
  ///
  /// If the declaration is not a member of context which can be named (record,
  /// namespace), it will return the 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;

  /// Print only the nested name specifier part of a fully-qualified name,
  /// including the '::' at the end. E.g.
  ///    when `printQualifiedName(D)` prints "A::B::i",
  ///    this function prints "A::B::".
  void printNestedNameSpecifier(raw_ostream &OS) const;
  void printNestedNameSpecifier(raw_ostream &OS,
                                const PrintingPolicy &Policy) const;

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

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

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

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

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

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

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

  /// Determine if the declaration obeys the reserved identifier rules of the
  /// given language.
  ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const;

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

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

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

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

  /// Determine whether this declaration can be redeclared in a
  /// different translation unit.
  bool isExternallyDeclarable() const {
    return isExternallyVisible() && !getOwningModuleForLinkage();
  }

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

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

  /// Kinds of explicit visibility.
  enum ExplicitVisibilityKind {
    /// Do an LV computation for, ultimately, a type.
    /// Visibility may be restricted by type visibility settings and
    /// the visibility of template arguments.
    VisibilityForType,

    /// Do an LV computation for, ultimately, a non-type declaration.
    /// Visibility may be restricted by value visibility settings and
    /// the visibility of template arguments.
    VisibilityForValue
  };

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

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

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

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

/// 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 {
  LabelStmt *TheStmt;
  StringRef MSAsmName;
  bool MSAsmNameResolved = false;

  /// 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), LocStart(StartL) {}

  void anchor() override;

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

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

  /// The ending location of the source range.
  SourceLocation RBraceLoc;

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

  using redeclarable_base = Redeclarable<NamespaceDecl>;

  NamespaceDecl *getNextRedeclarationImpl() override;
  NamespaceDecl *getPreviousDeclImpl() override;
  NamespaceDecl *getMostRecentDeclImpl() override;

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

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

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

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

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

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

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

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

  /// Returns true if the inline qualifier for \c Name is redundant.
  bool isRedundantInlineQualifierFor(DeclarationName Name) const {
    if (!isInline())
      return false;
    auto X = lookup(Name);
    // We should not perform a lookup within a transparent context, so find a
    // non-transparent parent context.
    auto Y = getParent()->getNonTransparentContext()->lookup(Name);
    return std::distance(X.begin(), X.end()) ==
      std::distance(Y.begin(), Y.end());
  }

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

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

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

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

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

  void anchor() override;

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

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

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

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

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

  QualifierInfo() = default;
  QualifierInfo(const QualifierInfo &) = delete;
  QualifierInfo& operator=(const QualifierInfo &) = delete;

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

/// Represents a ValueDecl that came out of a declarator.
/// Contains type source information through TypeSourceInfo.
class DeclaratorDecl : public ValueDecl {
  // A struct representing a TInfo, a trailing requires-clause and a syntactic
  // qualifier, to be used for the (uncommon) case of out-of-line declarations
  // and constrained function decls.
  struct ExtInfo : public QualifierInfo {
    TypeSourceInfo *TInfo;
    Expr *TrailingRequiresClause = nullptr;
  };

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

  /// 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:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

  TypeSourceInfo *getTypeSourceInfo() const {
    return hasExtInfo()
      ? getExtInfo()->TInfo
      : DeclInfo.get<TypeSourceInfo*>();
  }

  void setTypeSourceInfo(TypeSourceInfo *TI) {
    if (hasExtInfo())
      getExtInfo()->TInfo = TI;
    else
      DeclInfo = TI;
  }

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

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

  SourceRange getSourceRange() const override LLVM_READONLY;

  SourceLocation getBeginLoc() const LLVM_READONLY {
    return getOuterLocStart();
  }

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

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

  /// \brief Get the constraint-expression introduced by the trailing
  /// requires-clause in the function/member declaration, or null if no
  /// requires-clause was provided.
  Expr *getTrailingRequiresClause() {
    return hasExtInfo() ? getExtInfo()->TrailingRequiresClause
                        : nullptr;
  }

  const Expr *getTrailingRequiresClause() const {
    return hasExtInfo() ? getExtInfo()->TrailingRequiresClause
                        : nullptr;
  }

  void setTrailingRequiresClause(Expr *TrailingRequiresClause);

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

/// 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 {
  /// Whether this statement was already evaluated.
  bool WasEvaluated : 1;

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

  /// Whether this variable is known to have constant initialization. This is
  /// currently only computed in C++, for static / thread storage duration
  /// variables that might have constant initialization and for variables that
  /// are usable in constant expressions.
  bool HasConstantInitialization : 1;

  /// Whether this variable is known to have constant destruction. That is,
  /// whether running the destructor on the initial value is a side-effect
  /// (and doesn't inspect any state that might have changed during program
  /// execution). This is currently only computed if the destructor is
  /// non-trivial.
  bool HasConstantDestruction : 1;

  /// In C++98, whether the initializer is an ICE. This affects whether the
  /// variable is usable in constant expressions.
  bool HasICEInit : 1;
  bool CheckedForICEInit : 1;

  Stmt *Value;
  APValue Evaluated;

  EvaluatedStmt()
      : WasEvaluated(false), IsEvaluating(false),
        HasConstantInitialization(false), HasConstantDestruction(false),
        HasICEInit(false), CheckedForICEInit(false) {}
};

/// Represents a variable declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
  /// Initialization styles.
  enum InitializationStyle {
    /// C-style initialization with assignment
    CInit,

    /// Call-style initialization (C++98)
    CallInit,

    /// Direct list-initialization (C++11)
    ListInit
  };

  /// Kinds of thread-local storage.
  enum TLSKind {
    /// Not a TLS variable.
    TLS_None,

    /// TLS with a known-constant initializer.
    TLS_Static,

    /// TLS with a dynamic initializer.
    TLS_Dynamic
  };

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

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.
  using InitType = llvm::PointerUnion<Stmt *, EvaluatedStmt *>;

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

private:
  friend class ASTDeclReader;
  friend class ASTNodeImporter;
  friend class StmtIteratorBase;

  class VarDeclBitfields {
    friend class ASTDeclReader;
    friend class VarDecl;

    unsigned SClass : 3;
    unsigned TSCSpec : 2;
    unsigned InitStyle : 2;

    /// Whether this variable is an ARC pseudo-__strong variable; see
    /// isARCPseudoStrong() for details.
    unsigned ARCPseudoStrong : 1;
  };
  enum { NumVarDeclBits = 8 };

protected:
  enum { NumParameterIndexBits = 8 };

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

  enum { NumScopeDepthOrObjCQualsBits = 7 };

  class ParmVarDeclBitfields {
    friend class ASTDeclReader;
    friend class ParmVarDecl;

    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 : NumScopeDepthOrObjCQualsBits;

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

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

    unsigned : NumVarDeclBits;

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

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

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

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

    /// Whether this variable is the for-in loop declaration in Objective-C.
    unsigned ObjCForDecl : 1;

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

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

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

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

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

    unsigned EscapingByref : 1;
  };

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

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

  using redeclarable_base = Redeclarable<VarDecl>;

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

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

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

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

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

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

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

  SourceRange getSourceRange() const override LLVM_READONLY;

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

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

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

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

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

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

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

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

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

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

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

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

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

  /// 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 {
    /// This declaration is only a declaration.
    DeclarationOnly,

    /// This declaration is a tentative definition.
    TentativeDefinition,

    /// This declaration is definitely a definition.
    Definition
  };

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

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

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

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

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

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

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

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

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

  void setInit(Expr *I);

  /// Get the initializing declaration of this variable, if any. This is
  /// usually the definition, except that for a static data member it can be
  /// the in-class declaration.
  VarDecl *getInitializingDeclaration();
  const VarDecl *getInitializingDeclaration() const {
    return const_cast<VarDecl *>(this)->getInitializingDeclaration();
  }

  /// Determine whether this variable's value might be usable 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.
  ///
  /// This corresponds to C++20 [expr.const]p3's notion of a
  /// "potentially-constant" variable.
  bool mightBeUsableInConstantExpressions(const ASTContext &C) const;

  /// Determine whether this variable's value can be used in a
  /// constant expression, according to the relevant language standard,
  /// including checking whether it was initialized by a constant expression.
  bool isUsableInConstantExpressions(const ASTContext &C) const;

  EvaluatedStmt *ensureEvaluatedStmt() const;
  EvaluatedStmt *getEvaluatedStmt() const;

  /// Attempt to evaluate the value of the initializer attached to this
  /// declaration, and produce notes explaining why it cannot be evaluated.
  /// Returns a pointer to the value if evaluation succeeded, 0 otherwise.
  APValue *evaluateValue() const;

private:
  APValue *evaluateValueImpl(SmallVectorImpl<PartialDiagnosticAt> &Notes,
                             bool IsConstantInitialization) const;

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

  /// Evaluate the destruction of this variable to determine if it constitutes
  /// constant destruction.
  ///
  /// \pre hasConstantInitialization()
  /// \return \c true if this variable has constant destruction, \c false if
  ///         not.
  bool evaluateDestruction(SmallVectorImpl<PartialDiagnosticAt> &Notes) const;

  /// Determine whether this variable has constant initialization.
  ///
  /// This is only set in two cases: when the language semantics require
  /// constant initialization (globals in C and some globals in C++), and when
  /// the variable is usable in constant expressions (constexpr, const int, and
  /// reference variables in C++).
  bool hasConstantInitialization() const;

  /// Determine whether the initializer of this variable is an integer constant
  /// expression. For use in C++98, where this affects whether the variable is
  /// usable in constant expressions.
  bool hasICEInitializer(const ASTContext &Context) const;

  /// Evaluate the initializer of this variable to determine whether it's a
  /// constant initializer. Should only be called once, after completing the
  /// definition of the variable.
  bool checkForConstantInitialization(
      SmallVectorImpl<PartialDiagnosticAt> &Notes) const;

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

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

  /// Whether the initializer is a direct-initializer (list or call).
  bool isDirectInit() const {
    return getInitStyle() != CInit;
  }

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

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

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

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

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

  /// Determine whether this variable is a for-loop declaration for a
  /// for-in statement in Objective-C.
  bool isObjCForDecl() const {
    return NonParmVarDeclBits.ObjCForDecl;
  }

  void setObjCForDecl(bool FRD) {
    NonParmVarDeclBits.ObjCForDecl = FRD;
  }

  /// 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. There are 3 cases where this will be set, 1) if
  /// the variable is annotated with the objc_externally_retained attribute, 2)
  /// if its 'self' in a non-init method, or 3) if its the variable in an for-in
  /// loop.
  bool isARCPseudoStrong() const { return VarDeclBits.ARCPseudoStrong; }
  void setARCPseudoStrong(bool PS) { VarDeclBits.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;
  }

  /// Determine whether this variable is actually a function parameter pack or
  /// init-capture pack.
  bool isParameterPack() const;

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

  /// Indicates the capture is a __block variable that is captured by a block
  /// that can potentially escape (a block for which BlockDecl::doesNotEscape
  /// returns false).
  bool isEscapingByref() const;

  /// Indicates the capture is a __block variable that is never captured by an
  /// escaping block.
  bool isNonEscapingByref() const;

  void setEscapingByref() {
    NonParmVarDeclBits.EscapingByref = true;
  }

  /// Determines if this variable's alignment is dependent.
  bool hasDependentAlignment() const;

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

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

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

  /// Get the template specialization kind of this variable for the purposes of
  /// template instantiation. This differs from getTemplateSpecializationKind()
  /// for an instantiation of a class-scope explicit specialization.
  TemplateSpecializationKind
  getTemplateSpecializationKindForInstantiation() const;

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

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

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

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

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

  // Is this variable known to have a definition somewhere in the complete
  // program? This may be true even if the declaration has internal linkage and
  // has no definition within this source file.
  bool isKnownToBeDefined() const;

  /// Is destruction of this variable entirely suppressed? If so, the variable
  /// need not have a usable destructor at all.
  bool isNoDestroy(const ASTContext &) const;

  /// Would the destruction of this variable have any effect, and if so, what
  /// kind?
  QualType::DestructionKind needsDestruction(const ASTContext &Ctx) const;

  /// Whether this variable has a flexible array member initialized with one
  /// or more elements. This can only be called for declarations where
  /// hasInit() is true.
  ///
  /// (The standard doesn't allow initializing flexible array members; this is
  /// a gcc/msvc extension.)
  bool hasFlexibleArrayInit(const ASTContext &Ctx) const;

  /// If hasFlexibleArrayInit is true, compute the number of additional bytes
  /// necessary to store those elements. Otherwise, returns zero.
  ///
  /// This can only be called for declarations where hasInit() is true.
  CharUnits getFlexibleArrayInitChars(const ASTContext &Ctx) const;

  // 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 {
    /// Parameter for Objective-C 'self' argument
    ObjCSelf,

    /// Parameter for Objective-C '_cmd' argument
    ObjCCmd,

    /// Parameter for C++ 'this' argument
    CXXThis,

    /// Parameter for C++ virtual table pointers
    CXXVTT,

    /// Parameter for captured context
    CapturedContext,

    /// Parameter for Thread private variable
    ThreadPrivateVar,

    /// Other implicit parameter
    Other,
  };

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

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

  /// Determines whether this parameter is destroyed in the callee function.
  bool isDestroyedInCallee() const;

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

  static constexpr unsigned getMaxFunctionScopeDepth() {
    return (1u << NumScopeDepthOrObjCQualsBits) - 1;
  }

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

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

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

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

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

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

enum class MultiVersionKind {
  None,
  Target,
  CPUSpecific,
  CPUDispatch,
  TargetClones
};

/// Represents 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> {
  // This class stores some data in DeclContext::FunctionDeclBits
  // to save some space. Use the provided accessors to access it.
public:
  /// The kind of templated function a FunctionDecl can be.
  enum TemplatedKind {
    // Not templated.
    TK_NonTemplate,
    // The pattern in a function template declaration.
    TK_FunctionTemplate,
    // A non-template function that is an instantiation or explicit
    // specialization of a member of a templated class.
    TK_MemberSpecialization,
    // An instantiation or explicit specialization of a function template.
    // Note: this might have been instantiated from a templated class if it
    // is a class-scope explicit specialization.
    TK_FunctionTemplateSpecialization,
    // A function template specialization that hasn't yet been resolved to a
    // particular specialized function template.
    TK_DependentFunctionTemplateSpecialization
  };

  /// Stashed information about a defaulted function definition whose body has
  /// not yet been lazily generated.
  class DefaultedFunctionInfo final
      : llvm::TrailingObjects<DefaultedFunctionInfo, DeclAccessPair> {
    friend TrailingObjects;
    unsigned NumLookups;

  public:
    static DefaultedFunctionInfo *Create(ASTContext &Context,
                                         ArrayRef<DeclAccessPair> Lookups);
    /// Get the unqualified lookup results that should be used in this
    /// defaulted function definition.
    ArrayRef<DeclAccessPair> getUnqualifiedLookups() const {
      return {getTrailingObjects<DeclAccessPair>(), NumLookups};
    }
  };

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

  /// The active member of this union is determined by
  /// FunctionDeclBits.HasDefaultedFunctionInfo.
  union {
    /// The body of the function.
    LazyDeclStmtPtr Body;
    /// Information about a future defaulted function definition.
    DefaultedFunctionInfo *DefaultedInfo;
  };

  unsigned ODRHash;

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

  /// 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::PointerUnion<FunctionTemplateDecl *,
                     MemberSpecializationInfo *,
                     FunctionTemplateSpecializationInfo *,
                     DependentFunctionTemplateSpecializationInfo *>
    TemplateOrSpecialization;

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

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

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

  // This is unfortunately needed because ASTDeclWriter::VisitFunctionDecl
  // need to access this bit but we want to avoid making ASTDeclWriter
  // a friend of FunctionDeclBitfields just for this.
  bool isDeletedBit() const { return FunctionDeclBits.IsDeleted; }

  /// Whether an ODRHash has been stored.
  bool hasODRHash() const { return FunctionDeclBits.HasODRHash; }

  /// State that an ODRHash has been stored.
  void setHasODRHash(bool B = true) { FunctionDeclBits.HasODRHash = B; }

protected:
  FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
               const DeclarationNameInfo &NameInfo, QualType T,
               TypeSourceInfo *TInfo, StorageClass S, bool UsesFPIntrin,
               bool isInlineSpecified, ConstexprSpecKind ConstexprKind,
               Expr *TrailingRequiresClause = nullptr);

  using redeclarable_base = Redeclarable<FunctionDecl>;

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

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

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

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

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

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

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

  static FunctionDecl *
  Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
         const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
         StorageClass SC, bool UsesFPIntrin, bool isInlineSpecified,
         bool hasWrittenPrototype, ConstexprSpecKind ConstexprKind,
         Expr *TrailingRequiresClause);

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

  /// Returns the location of the ellipsis of a variadic function.
  SourceLocation getEllipsisLoc() const {
    const auto *FPT = getType()->getAs<FunctionProtoType>();
    if (FPT && FPT->isVariadic())
      return FPT->getEllipsisLoc();
    return SourceLocation();
  }

  SourceRange getSourceRange() const override LLVM_READONLY;

  // Function definitions.
  //
  // A function declaration may be:
  // - a non defining declaration,
  // - a definition. A function may be defined because:
  //   - it has a body, or will have it in the case of late parsing.
  //   - it has an uninstantiated body. The body does not exist because the
  //     function is not used yet, but the declaration is considered a
  //     definition and does not allow other definition of this function.
  //   - it does not have a user specified body, but it does not allow
  //     redefinition, because it is deleted/defaulted or is defined through
  //     some other mechanism (alias, ifunc).

  /// Returns true if the function has a body.
  ///
  /// 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);
  }

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

  /// Returns true if the function has a definition that does not need to be
  /// instantiated.
  ///
  /// The variant that accepts a FunctionDecl pointer will set that function
  /// declaration to the declaration that is a definition (if there is one).
  ///
  /// \param CheckForPendingFriendDefinition If \c true, also check for friend
  ///        declarations that were instantiataed from function definitions.
  ///        Such a declaration behaves as if it is a definition for the
  ///        purpose of redefinition checking, but isn't actually a "real"
  ///        definition until its body is instantiated.
  bool isDefined(const FunctionDecl *&Definition,
                 bool CheckForPendingFriendDefinition = false) const;

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

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

  /// 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.
  ///
  /// Note: the function declaration does not become a definition until the
  /// parser reaches the definition, if called before, this function will return
  /// `false`.
  bool isThisDeclarationADefinition() const {
    return isDeletedAsWritten() || isDefaulted() ||
           doesThisDeclarationHaveABody() || hasSkippedBody() ||
           willHaveBody() || hasDefiningAttr();
  }

  /// Determine whether this specific declaration of the function is a friend
  /// declaration that was instantiated from a function definition. Such
  /// declarations behave like definitions in some contexts.
  bool isThisDeclarationInstantiatedFromAFriendDefinition() const;

  /// Returns whether this specific declaration of the function has a body.
  bool doesThisDeclarationHaveABody() const {
    return (!FunctionDeclBits.HasDefaultedFunctionInfo && Body) ||
           isLateTemplateParsed();
  }

  void setBody(Stmt *B);
  void setLazyBody(uint64_t Offset) {
    FunctionDeclBits.HasDefaultedFunctionInfo = false;
    Body = LazyDeclStmtPtr(Offset);
  }

  void setDefaultedFunctionInfo(DefaultedFunctionInfo *Info);
  DefaultedFunctionInfo *getDefaultedFunctionInfo() const;

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

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

  /// State that this function is marked as virtual explicitly.
  void setVirtualAsWritten(bool V) { FunctionDeclBits.IsVirtualAsWritten = V; }

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

  /// Whether this templated function will be late parsed.
  bool isLateTemplateParsed() const {
    return FunctionDeclBits.IsLateTemplateParsed;
  }

  /// State that this templated function will be late parsed.
  void setLateTemplateParsed(bool ILT = true) {
    FunctionDeclBits.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 FunctionDeclBits.IsTrivial; }
  void setTrivial(bool IT) { FunctionDeclBits.IsTrivial = IT; }

  bool isTrivialForCall() const { return FunctionDeclBits.IsTrivialForCall; }
  void setTrivialForCall(bool IT) { FunctionDeclBits.IsTrivialForCall = IT; }

  /// Whether this function is defaulted. Valid for e.g.
  /// special member functions, defaulted comparisions (not methods!).
  bool isDefaulted() const { return FunctionDeclBits.IsDefaulted; }
  void setDefaulted(bool D = true) { FunctionDeclBits.IsDefaulted = D; }

  /// Whether this function is explicitly defaulted.
  bool isExplicitlyDefaulted() const {
    return FunctionDeclBits.IsExplicitlyDefaulted;
  }

  /// State that this function is explicitly defaulted.
  void setExplicitlyDefaulted(bool ED = true) {
    FunctionDeclBits.IsExplicitlyDefaulted = ED;
  }

  /// True if this method is user-declared and was not
  /// deleted or defaulted on its first declaration.
  bool isUserProvided() const {
    auto *DeclAsWritten = this;
    if (FunctionDecl *Pattern = getTemplateInstantiationPattern())
      DeclAsWritten = Pattern;
    return !(DeclAsWritten->isDeleted() ||
             DeclAsWritten->getCanonicalDecl()->isDefaulted());
  }

  /// 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 FunctionDeclBits.HasImplicitReturnZero;
  }

  /// State that 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.
  void setHasImplicitReturnZero(bool IRZ) {
    FunctionDeclBits.HasImplicitReturnZero = IRZ;
  }

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

  /// Whether this function has a written prototype.
  bool hasWrittenPrototype() const {
    return FunctionDeclBits.HasWrittenPrototype;
  }

  /// State that this function has a written prototype.
  void setHasWrittenPrototype(bool P = true) {
    FunctionDeclBits.HasWrittenPrototype = P;
  }

  /// Whether this function inherited its prototype from a
  /// previous declaration.
  bool hasInheritedPrototype() const {
    return FunctionDeclBits.HasInheritedPrototype;
  }

  /// State that this function inherited its prototype from a
  /// previous declaration.
  void setHasInheritedPrototype(bool P = true) {
    FunctionDeclBits.HasInheritedPrototype = P;
  }

  /// Whether this is a (C++11) constexpr function or constexpr constructor.
  bool isConstexpr() const {
    return getConstexprKind() != ConstexprSpecKind::Unspecified;
  }
  void setConstexprKind(ConstexprSpecKind CSK) {
    FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(CSK);
  }
  ConstexprSpecKind getConstexprKind() const {
    return static_cast<ConstexprSpecKind>(FunctionDeclBits.ConstexprKind);
  }
  bool isConstexprSpecified() const {
    return getConstexprKind() == ConstexprSpecKind::Constexpr;
  }
  bool isConsteval() const {
    return getConstexprKind() == ConstexprSpecKind::Consteval;
  }

  /// 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 FunctionDeclBits.InstantiationIsPending;
  }

  /// State that the instantiation of this function is pending.
  /// (see instantiationIsPending)
  void setInstantiationIsPending(bool IC) {
    FunctionDeclBits.InstantiationIsPending = IC;
  }

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

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

  bool isDeletedAsWritten() const {
    return FunctionDeclBits.IsDeleted && !isDefaulted();
  }

  void setDeletedAsWritten(bool D = true) { FunctionDeclBits.IsDeleted = D; }

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

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

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

  /// 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
  /// the parameter number of the requested alignment through AlignmentParam.
  ///
  /// If this function is an allocation/deallocation function that takes
  /// the `std::nothrow_t` tag, return true through IsNothrow,
  bool isReplaceableGlobalAllocationFunction(
      Optional<unsigned> *AlignmentParam = nullptr,
      bool *IsNothrow = nullptr) const;

  /// Determine if this function provides an inline implementation of a builtin.
  bool isInlineBuiltinDeclaration() const;

  /// Determine whether this is a destroying operator delete.
  bool isDestroyingOperatorDelete() const;

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

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

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

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

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

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

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

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

  /// True if this function is considered a multiversioned function.
  bool isMultiVersion() const {
    return getCanonicalDecl()->FunctionDeclBits.IsMultiVersion;
  }

  /// Sets the multiversion state for this declaration and all of its
  /// redeclarations.
  void setIsMultiVersion(bool V = true) {
    getCanonicalDecl()->FunctionDeclBits.IsMultiVersion = V;
  }

  /// Gets the kind of multiversioning attribute this declaration has. Note that
  /// this can return a value even if the function is not multiversion, such as
  /// the case of 'target'.
  MultiVersionKind getMultiVersionKind() const;


  /// True if this function is a multiversioned dispatch function as a part of
  /// the cpu_specific/cpu_dispatch functionality.
  bool isCPUDispatchMultiVersion() const;
  /// True if this function is a multiversioned processor specific function as a
  /// part of the cpu_specific/cpu_dispatch functionality.
  bool isCPUSpecificMultiVersion() const;

  /// True if this function is a multiversioned dispatch function as a part of
  /// the target functionality.
  bool isTargetMultiVersion() const;

  /// True if this function is a multiversioned dispatch function as a part of
  /// the target-clones functionality.
  bool isTargetClonesMultiVersion() const;

  /// \brief Get the associated-constraints of this function declaration.
  /// Currently, this will either be a vector of size 1 containing the
  /// trailing-requires-clause or an empty vector.
  ///
  /// Use this instead of getTrailingRequiresClause for concepts APIs that
  /// accept an ArrayRef of constraint expressions.
  void getAssociatedConstraints(SmallVectorImpl<const Expr *> &AC) const {
    if (auto *TRC = getTrailingRequiresClause())
      AC.push_back(TRC);
  }

  void setPreviousDeclaration(FunctionDecl * PrevDecl);

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

  unsigned getBuiltinID(bool ConsiderWrapperFunctions = false) const;

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

  // Iterator access to formal parameters.
  using param_iterator = MutableArrayRef<ParmVarDecl *>::iterator;
  using param_const_iterator = ArrayRef<ParmVarDecl *>::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(); }

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

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

  /// Determine whether this function has a single parameter, or multiple
  /// parameters where all but the first have default arguments.
  ///
  /// This notion is used in the definition of copy/move constructors and
  /// initializer list constructors. Note that, unlike getMinRequiredArguments,
  /// parameter packs are not treated specially here.
  bool hasOneParamOrDefaultArgs() const;

  /// Find the source location information for how the type of this function
  /// was written. May be absent (for example if the function was declared via
  /// a typedef) and may contain a different type from that of the function
  /// (for example if the function type was adjusted by an attribute).
  FunctionTypeLoc getFunctionTypeLoc() const;

  QualType getReturnType() const {
    return getType()->castAs<FunctionType>()->getReturnType();
  }

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

  /// Attempt to compute an informative source range covering the
  /// function parameters, including the ellipsis of a variadic function.
  /// The source range excludes the parentheses, and is invalid if there are
  /// no parameters and no ellipsis.
  SourceRange getParametersSourceRange() const;

  /// Get the declared return type, which may differ from the actual return
  /// type if the return type is deduced.
  QualType getDeclaredReturnType() const {
    auto *TSI = getTypeSourceInfo();
    QualType T = TSI ? TSI->getType() : getType();
    return T->castAs<FunctionType>()->getReturnType();
  }

  /// Gets the ExceptionSpecificationType as declared.
  ExceptionSpecificationType getExceptionSpecType() const {
    auto *TSI = getTypeSourceInfo();
    QualType T = TSI ? TSI->getType() : getType();
    const auto *FPT = T->getAs<FunctionProtoType>();
    return FPT ? FPT->getExceptionSpecType() : EST_None;
  }

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

  /// Determine the type of an expression that calls this function.
  QualType getCallResultType() const {
    return getType()->castAs<FunctionType>()->getCallResultType(
        getASTContext());
  }

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

  /// Sets the storage class as written in the source.
  void setStorageClass(StorageClass SClass) {
    FunctionDeclBits.SClass = SClass;
  }

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

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

  /// Determine whether the function was declared in source context
  /// that requires constrained FP intrinsics
  bool UsesFPIntrin() const { return FunctionDeclBits.UsesFPIntrin; }

  /// Set whether the function was declared in source context
  /// that requires constrained FP intrinsics
  void setUsesFPIntrin(bool I) { FunctionDeclBits.UsesFPIntrin = I; }

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

  /// 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 FunctionDeclBits.IsInline; }

  bool isInlineDefinitionExternallyVisible() const;

  bool isMSExternInline() const;

  bool doesDeclarationForceExternallyVisibleDefinition() const;

  bool isStatic() const { return getStorageClass() == SC_Static; }

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

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

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

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

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

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

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

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

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

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

  /// 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).
  ///
  /// If \p ForDefinition is \c false, explicit specializations will be treated
  /// as if they were implicit instantiations. This will then find the pattern
  /// corresponding to non-definition portions of the declaration, such as
  /// default arguments and the exception specification.
  FunctionDecl *
  getTemplateInstantiationPattern(bool ForDefinition = true) const;

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

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

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

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

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

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

  /// Determine the kind of template specialization this function represents
  /// for the purpose of template instantiation.
  TemplateSpecializationKind
  getTemplateSpecializationKindForInstantiation() const;

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

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

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

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

  /// Returns ODRHash of the function.  This value is calculated and
  /// stored on first call, then the stored value returned on the other calls.
  unsigned getODRHash();

  /// Returns cached ODRHash of the function.  This must have been previously
  /// computed and stored.
  unsigned getODRHash() 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));
  }
};

/// Represents a member of a struct/union/class.
class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> {
  unsigned BitField : 1;
  unsigned Mutable : 1;
  mutable unsigned CachedFieldIndex : 30;

  /// 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_NoInit = (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,
  };

  /// If this is a bitfield with a default member initializer, this
  /// structure is used to represent the two expressions.
  struct InitAndBitWidth {
    Expr *Init;
    Expr *BitWidth;
  };

  /// Storage for either the bit-width, the in-class initializer, or
  /// both (via InitAndBitWidth), or the captured variable length array bound.
  ///
  /// If the storage kind is ISK_InClassCopyInit or
  /// ISK_InClassListInit, but the initializer is null, then this
  /// field has an in-class initializer that has not yet been parsed
  /// and attached.
  // FIXME: Tail-allocate this to reduce the size of FieldDecl in the
  // overwhelmingly common case that we have none of these things.
  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),
      BitField(false), Mutable(Mutable), CachedFieldIndex(0),
      InitStorage(nullptr, (InitStorageKind) InitStyle) {
    if (BW)
      setBitWidth(BW);
  }

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

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

  /// Returns the index of this field within its record,
  /// as appropriate for passing to ASTRecordLayout::getFieldOffset.
  unsigned getFieldIndex() const;

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

  /// Determines whether this field is a bitfield.
  bool isBitField() const { return BitField; }

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

  /// 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 {
    if (!BitField)
      return nullptr;
    void *Ptr = InitStorage.getPointer();
    if (getInClassInitStyle())
      return static_cast<InitAndBitWidth*>(Ptr)->BitWidth;
    return static_cast<Expr*>(Ptr);
  }

  unsigned getBitWidthValue(const ASTContext &Ctx) const;

  /// Set the bit-field width for this member.
  // Note: used by some clients (i.e., do not remove it).
  void setBitWidth(Expr *Width) {
    assert(!hasCapturedVLAType() && !BitField &&
           "bit width or captured type already set");
    assert(Width && "no bit width specified");
    InitStorage.setPointer(
        InitStorage.getInt()
            ? new (getASTContext())
                  InitAndBitWidth{getInClassInitializer(), Width}
            : static_cast<void*>(Width));
    BitField = true;
  }

  /// 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.setPointer(getInClassInitializer());
    BitField = false;
  }

  /// Is this a zero-length bit-field? Such bit-fields aren't really bit-fields
  /// at all and instead act as a separator between contiguous runs of other
  /// bit-fields.
  bool isZeroLengthBitField(const ASTContext &Ctx) const;

  /// Determine if this field is a subobject of zero size, that is, either a
  /// zero-length bit-field or a field of empty class type with the
  /// [[no_unique_address]] attribute.
  bool isZeroSize(const ASTContext &Ctx) const;

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

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

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

  /// Set the C++11 in-class initializer for this member.
  void setInClassInitializer(Expr *Init) {
    assert(hasInClassInitializer() && !getInClassInitializer());
    if (BitField)
      static_cast<InitAndBitWidth*>(InitStorage.getPointer())->Init = Init;
    else
      InitStorage.setPointer(Init);
  }

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

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

  /// Get the captured variable length array type.
  const VariableArrayType *getCapturedVLAType() const {
    return hasCapturedVLAType() ? static_cast<const VariableArrayType *>(
                                      InitStorage.getPointer())
                                : nullptr;
  }

  /// Set the captured variable length array type for this field.
  void setCapturedVLAType(const VariableArrayType *VLAType);

  /// Returns the parent of this field declaration, which
  /// is the struct in which this field is defined.
  ///
  /// Returns null if this is not a normal class/struct field declaration, e.g.
  /// ObjCAtDefsFieldDecl, ObjCIvarDecl.
  const RecordDecl *getParent() const {
    return dyn_cast<RecordDecl>(getDeclContext());
  }

  RecordDecl *getParent() {
    return dyn_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; }
};

/// 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:
  friend class StmtIteratorBase;

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

/// Represents a field injected from an anonymous union/struct into the parent
/// scope. These are always implicit.
class IndirectFieldDecl : public ValueDecl,
                          public Mergeable<IndirectFieldDecl> {
  NamedDecl **Chaining;
  unsigned ChainingSize;

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

  void anchor() override;

public:
  friend class ASTDeclReader;

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

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

  using chain_iterator = ArrayRef<NamedDecl *>::const_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; }
};

/// Represents a declaration of a type.
class TypeDecl : public NamedDecl {
  friend class ASTContext;

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

  /// The start of the source range for this declaration.
  SourceLocation LocStart;

  void anchor() override;

protected:
  TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
           SourceLocation StartL = SourceLocation())
    : NamedDecl(DK, DC, L, Id), 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 getBeginLoc() 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> {
  struct alignas(8) ModedTInfo {
    TypeSourceInfo *first;
    QualType second;
  };

  /// If int part is 0, we have not computed IsTransparentTag.
  /// Otherwise, IsTransparentTag is (getInt() >> 1).
  mutable llvm::PointerIntPair<
      llvm::PointerUnion<TypeSourceInfo *, ModedTInfo *>, 2>
      MaybeModedTInfo;

  void anchor() override;

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, 0) {}

  using redeclarable_base = Redeclarable<TypedefNameDecl>;

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

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

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

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

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

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

  TypeSourceInfo *getTypeSourceInfo() const {
    return isModed() ? MaybeModedTInfo.getPointer().get<ModedTInfo *>()->first
                     : MaybeModedTInfo.getPointer().get<TypeSourceInfo *>();
  }

  QualType getUnderlyingType() const {
    return isModed() ? MaybeModedTInfo.getPointer().get<ModedTInfo *>()->second
                     : MaybeModedTInfo.getPointer()
                           .get<TypeSourceInfo *>()
                           ->getType();
  }

  void setTypeSourceInfo(TypeSourceInfo *newType) {
    MaybeModedTInfo.setPointer(newType);
  }

  void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) {
    MaybeModedTInfo.setPointer(new (getASTContext(), 8)
                                   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 (MaybeModedTInfo.getInt())
      return MaybeModedTInfo.getInt() & 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;
};

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

/// Represents the declaration of a typedef-name via a C++11
/// 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; }
};

/// Represents the declaration of a struct/union/class/enum.
class TagDecl : public TypeDecl,
                public DeclContext,
                public Redeclarable<TagDecl> {
  // This class stores some data in DeclContext::TagDeclBits
  // to save some space. Use the provided accessors to access it.
public:
  // This is really ugly.
  using TagKind = TagTypeKind;

private:
  SourceRange BraceRange;

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

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

  using redeclarable_base = Redeclarable<TagDecl>;

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

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

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

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

  /// True if this decl is currently being defined.
  void setBeingDefined(bool V = true) { TagDeclBits.IsBeingDefined = V; }

  /// 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.
  void setMayHaveOutOfDateDef(bool V = true) {
    TagDeclBits.MayHaveOutOfDateDef = V;
  }

public:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;

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

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

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

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

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

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

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

  /// True if this decl has its body fully specified.
  void setCompleteDefinition(bool V = true) {
    TagDeclBits.IsCompleteDefinition = V;
  }

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

  /// True if this complete decl is
  /// required to be complete for some existing use.
  void setCompleteDefinitionRequired(bool V = true) {
    TagDeclBits.IsCompleteDefinitionRequired = V;
  }

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

  /// True if this tag declaration is "embedded" (i.e., defined or declared
  /// for the very first time) in the syntax of a declarator.
  bool isEmbeddedInDeclarator() const {
    return TagDeclBits.IsEmbeddedInDeclarator;
  }

  /// True if this tag declaration is "embedded" (i.e., defined or declared
  /// for the very first time) in the syntax of a declarator.
  void setEmbeddedInDeclarator(bool isInDeclarator) {
    TagDeclBits.IsEmbeddedInDeclarator = isInDeclarator;
  }

  /// True if this tag is free standing, e.g. "struct foo;".
  bool isFreeStanding() const { return TagDeclBits.IsFreeStanding; }

  /// True if this tag is free standing, e.g. "struct foo;".
  void setFreeStanding(bool isFreeStanding = true) {
    TagDeclBits.IsFreeStanding = isFreeStanding;
  }

  /// 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.
  bool mayHaveOutOfDateDef() const { return TagDeclBits.MayHaveOutOfDateDef; }

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

  /// Whether this declaration was a definition in some module but was forced
  /// to be a declaration.
  ///
  /// Useful for clients checking if a module has a definition of a specific
  /// symbol and not interested in the final AST with deduplicated definitions.
  bool isThisDeclarationADemotedDefinition() const {
    return TagDeclBits.IsThisDeclarationADemotedDefinition;
  }

  /// Mark a definition as a declaration and maintain information it _was_
  /// a definition.
  void demoteThisDefinitionToDeclaration() {
    assert(isCompleteDefinition() &&
           "Should demote definitions only, not forward declarations");
    setCompleteDefinition(false);
    TagDeclBits.IsThisDeclarationADemotedDefinition = true;
  }

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

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

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

  TagKind getTagKind() const {
    return static_cast<TagKind>(TagDeclBits.TagDeclKind);
  }

  void setTagKind(TagKind TK) { TagDeclBits.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);

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

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

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

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

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

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

  /// Store the ODRHash after first calculation.
  /// The corresponding flag HasODRHash is in EnumDeclBits
  /// and can be accessed with the provided accessors.
  unsigned ODRHash;

  EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
           SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
           bool Scoped, bool ScopedUsingClassTag, bool Fixed);

  void anchor() override;

  void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
                                    TemplateSpecializationKind TSK);

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

  /// Returns the width in bits required to store all the
  /// negative enumerators of this enum. (see getNumNegativeBits)
  void setNumNegativeBits(unsigned Num) { EnumDeclBits.NumNegativeBits = Num; }

public:
  /// True if this tag declaration is a scoped enumeration. Only
  /// possible in C++11 mode.
  void setScoped(bool Scoped = true) { EnumDeclBits.IsScoped = Scoped; }

  /// 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.
  void setScopedUsingClassTag(bool ScopedUCT = true) {
    EnumDeclBits.IsScopedUsingClassTag = ScopedUCT;
  }

  /// True if this is an Objective-C, C++11, or
  /// Microsoft-style enumeration with a fixed underlying type.
  void setFixed(bool Fixed = true) { EnumDeclBits.IsFixed = Fixed; }

private:
  /// True if a valid hash is stored in ODRHash.
  bool hasODRHash() const { return EnumDeclBits.HasODRHash; }
  void setHasODRHash(bool Hash = true) { EnumDeclBits.HasODRHash = Hash; }

public:
  friend class ASTDeclReader;

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

  /// Overrides to provide correct range when there's an enum-base specifier
  /// with forward declarations.
  SourceRange getSourceRange() const override LLVM_READONLY;

  /// When created, the EnumDecl corresponds to a
  /// forward-declared enum. This method is used to mark the
  /// declaration as being defined; its 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);

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

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

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

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

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

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

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

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

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

  /// Returns the width in bits required to store all the
  /// non-negative enumerators of this enum.
  unsigned getNumPositiveBits() const { return EnumDeclBits.NumPositiveBits; }

  /// 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 EnumDeclBits.NumNegativeBits; }

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

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

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

  unsigned getODRHash();

  /// Returns true if this can be considered a complete type.
  bool isComplete() const {
    // IntegerType is set for fixed type enums and non-fixed but implicitly
    // int-sized Microsoft enums.
    return isCompleteDefinition() || IntegerType;
  }

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

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

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

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

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

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

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

/// 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 {
  // This class stores some data in DeclContext::RecordDeclBits
  // to save some space. Use the provided accessors to access it.
public:
  friend class DeclContext;
  /// Enum that represents the different ways arguments are passed to and
  /// returned from function calls. This takes into account the target-specific
  /// and version-specific rules along with the rules determined by the
  /// language.
  enum ArgPassingKind : unsigned {
    /// The argument of this type can be passed directly in registers.
    APK_CanPassInRegs,

    /// The argument of this type cannot be passed directly in registers.
    /// Records containing this type as a subobject are not forced to be passed
    /// indirectly. This value is used only in C++. This value is required by
    /// C++ because, in uncommon situations, it is possible for a class to have
    /// only trivial copy/move constructors even when one of its subobjects has
    /// a non-trivial copy/move constructor (if e.g. the corresponding copy/move
    /// constructor in the derived class is deleted).
    APK_CannotPassInRegs,

    /// The argument of this type cannot be passed directly in registers.
    /// Records containing this type as a subobject are forced to be passed
    /// indirectly.
    APK_CanNeverPassInRegs
  };

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 RecordDeclBits.HasFlexibleArrayMember;
  }

  void setHasFlexibleArrayMember(bool V) {
    RecordDeclBits.HasFlexibleArrayMember = V;
  }

  /// 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 RecordDeclBits.AnonymousStructOrUnion;
  }

  void setAnonymousStructOrUnion(bool Anon) {
    RecordDeclBits.AnonymousStructOrUnion = Anon;
  }

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

  bool hasVolatileMember() const { return RecordDeclBits.HasVolatileMember; }

  void setHasVolatileMember(bool val) {
    RecordDeclBits.HasVolatileMember = val;
  }

  bool hasLoadedFieldsFromExternalStorage() const {
    return RecordDeclBits.LoadedFieldsFromExternalStorage;
  }

  void setHasLoadedFieldsFromExternalStorage(bool val) const {
    RecordDeclBits.LoadedFieldsFromExternalStorage = val;
  }

  /// Functions to query basic properties of non-trivial C structs.
  bool isNonTrivialToPrimitiveDefaultInitialize() const {
    return RecordDeclBits.NonTrivialToPrimitiveDefaultInitialize;
  }

  void setNonTrivialToPrimitiveDefaultInitialize(bool V) {
    RecordDeclBits.NonTrivialToPrimitiveDefaultInitialize = V;
  }

  bool isNonTrivialToPrimitiveCopy() const {
    return RecordDeclBits.NonTrivialToPrimitiveCopy;
  }

  void setNonTrivialToPrimitiveCopy(bool V) {
    RecordDeclBits.NonTrivialToPrimitiveCopy = V;
  }

  bool isNonTrivialToPrimitiveDestroy() const {
    return RecordDeclBits.NonTrivialToPrimitiveDestroy;
  }

  void setNonTrivialToPrimitiveDestroy(bool V) {
    RecordDeclBits.NonTrivialToPrimitiveDestroy = V;
  }

  bool hasNonTrivialToPrimitiveDefaultInitializeCUnion() const {
    return RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion;
  }

  void setHasNonTrivialToPrimitiveDefaultInitializeCUnion(bool V) {
    RecordDeclBits.HasNonTrivialToPrimitiveDefaultInitializeCUnion = V;
  }

  bool hasNonTrivialToPrimitiveDestructCUnion() const {
    return RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion;
  }

  void setHasNonTrivialToPrimitiveDestructCUnion(bool V) {
    RecordDeclBits.HasNonTrivialToPrimitiveDestructCUnion = V;
  }

  bool hasNonTrivialToPrimitiveCopyCUnion() const {
    return RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion;
  }

  void setHasNonTrivialToPrimitiveCopyCUnion(bool V) {
    RecordDeclBits.HasNonTrivialToPrimitiveCopyCUnion = V;
  }

  /// Determine whether this class can be passed in registers. In C++ mode,
  /// it must have at least one trivial, non-deleted copy or move constructor.
  /// FIXME: This should be set as part of completeDefinition.
  bool canPassInRegisters() const {
    return getArgPassingRestrictions() == APK_CanPassInRegs;
  }

  ArgPassingKind getArgPassingRestrictions() const {
    return static_cast<ArgPassingKind>(RecordDeclBits.ArgPassingRestrictions);
  }

  void setArgPassingRestrictions(ArgPassingKind Kind) {
    RecordDeclBits.ArgPassingRestrictions = Kind;
  }

  bool isParamDestroyedInCallee() const {
    return RecordDeclBits.ParamDestroyedInCallee;
  }

  void setParamDestroyedInCallee(bool V) {
    RecordDeclBits.ParamDestroyedInCallee = V;
  }

  bool isRandomized() const { return RecordDeclBits.IsRandomized; }

  void setIsRandomized(bool V) { RecordDeclBits.IsRandomized = V; }

  void reorderDecls(const SmallVectorImpl<Decl *> &Decls);

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

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

  /// Determine whether this record is a record for captured variables in
  /// CapturedStmt construct.
  bool isCapturedRecord() const;

  /// Mark the record as a record for captured variables in CapturedStmt
  /// construct.
  void setCapturedRecord();

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

  /// Returns whether this record is a union, or contains (at any nesting level)
  /// a union member. This is used by CMSE to warn about possible information
  /// leaks.
  bool isOrContainsUnion() const;

  // 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.
  using field_iterator = specific_decl_iterator<FieldDecl>;
  using field_range = llvm::iterator_range<specific_decl_iterator<FieldDecl>>;

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

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

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

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

  /// 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:
  /// Deserialize just the fields.
  void LoadFieldsFromExternalStorage() const;
};

class FileScopeAsmDecl : public Decl {
  StringLiteral *AsmString;
  SourceLocation RParenLoc;

  FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring,
                   SourceLocation StartL, SourceLocation EndL)
    : Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {}

  virtual void anchor();

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

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

    bool isEscapingByref() const {
      return getVariable()->isEscapingByref();
    }

    bool isNonEscapingByref() const {
      return getVariable()->isNonEscapingByref();
    }

    /// 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:
  /// A 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 = nullptr;
  unsigned NumParams = 0;

  Stmt *Body = nullptr;
  TypeSourceInfo *SignatureAsWritten = nullptr;

  const Capture *Captures = nullptr;
  unsigned NumCaptures = 0;

  unsigned ManglingNumber = 0;
  Decl *ManglingContextDecl = nullptr;

protected:
  BlockDecl(DeclContext *DC, SourceLocation CaretLoc);

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 BlockDeclBits.IsVariadic; }
  void setIsVariadic(bool value) { BlockDeclBits.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.
  using param_iterator = MutableArrayRef<ParmVarDecl *>::iterator;
  using param_const_iterator = ArrayRef<ParmVarDecl *>::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);

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

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

  using capture_const_iterator = ArrayRef<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 BlockDeclBits.CapturesCXXThis; }
  void setCapturesCXXThis(bool B = true) { BlockDeclBits.CapturesCXXThis = B; }

  bool blockMissingReturnType() const {
    return BlockDeclBits.BlockMissingReturnType;
  }

  void setBlockMissingReturnType(bool val = true) {
    BlockDeclBits.BlockMissingReturnType = val;
  }

  bool isConversionFromLambda() const {
    return BlockDeclBits.IsConversionFromLambda;
  }

  void setIsConversionFromLambda(bool val = true) {
    BlockDeclBits.IsConversionFromLambda = val;
  }

  bool doesNotEscape() const { return BlockDeclBits.DoesNotEscape; }
  void setDoesNotEscape(bool B = true) { BlockDeclBits.DoesNotEscape = B; }

  bool canAvoidCopyToHeap() const {
    return BlockDeclBits.CanAvoidCopyToHeap;
  }
  void setCanAvoidCopyToHeap(bool B = true) {
    BlockDeclBits.CanAvoidCopyToHeap = B;
  }

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

/// 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:
  /// The number of parameters to the outlined function.
  unsigned NumParams;

  /// The position of context parameter in list of parameters.
  unsigned ContextParam;

  /// 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:
  friend class ASTDeclReader;
  friend class ASTDeclWriter;
  friend TrailingObjects;

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

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

  using param_iterator = ImplicitParamDecl *const *;
  using param_range = llvm::iterator_range<param_iterator>;

  /// Retrieve an iterator pointing to the first parameter decl.
  param_iterator param_begin() const { return getParams(); }
  /// 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));
  }
};

/// 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
///
/// A C++20 module import declaration imports the named module or partition.
/// Periods are permitted in C++20 module names, but have no semantic meaning.
/// For example:
/// \code
///   import NamedModule;
///   import :SomePartition; // Must be a partition of the current module.
///   import Names.Like.this; // Allowed.
///   import :and.Also.Partition.names;
/// \endcode
///
/// Import declarations can also be implicitly generated from
/// \#include/\#import directives.
class ImportDecl final : public Decl,
                         llvm::TrailingObjects<ImportDecl, SourceLocation> {
  friend class ASTContext;
  friend class ASTDeclReader;
  friend class ASTReader;
  friend TrailingObjects;

  /// The imported module.
  Module *ImportedModule = nullptr;

  /// The next import in the list of imports local to the translation
  /// unit being parsed (not loaded from an AST file).
  ///
  /// Includes 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<ImportDecl *, 1, bool> NextLocalImportAndComplete;

  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) {}

  bool isImportComplete() const { return NextLocalImportAndComplete.getInt(); }

  void setImportComplete(bool C) { NextLocalImportAndComplete.setInt(C); }

  /// The next import in the list of imports local to the translation
  /// unit being parsed (not loaded from an AST file).
  ImportDecl *getNextLocalImport() const {
    return NextLocalImportAndComplete.getPointer();
  }

  void setNextLocalImport(ImportDecl *Import) {
    NextLocalImportAndComplete.setPointer(Import);
  }

public:
  /// Create a new module import declaration.
  static ImportDecl *Create(ASTContext &C, DeclContext *DC,
                            SourceLocation StartLoc, Module *Imported,
                            ArrayRef<SourceLocation> IdentifierLocs);

  /// Create a new module import declaration for an implicitly-generated
  /// import.
  static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC,
                                    SourceLocation StartLoc, Module *Imported,
                                    SourceLocation EndLoc);

  /// Create a new, deserialized module import declaration.
  static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID,
                                        unsigned NumLocations);

  /// Retrieve the module that was imported by the import declaration.
  Module *getImportedModule() const { return ImportedModule; }

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

/// 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:
  friend class ASTDeclReader;

  /// The source location for the right brace (if valid).
  SourceLocation RBraceLoc;

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

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

  bool hasBraces() const { return RBraceLoc.isValid(); }

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

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

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

/// Represents an empty-declaration.
class EmptyDecl : public Decl {
  EmptyDecl(DeclContext *DC, SourceLocation L) : Decl(Empty, DC, L) {}

  virtual void anchor();

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 StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD,
                                             const NamedDecl *ND) {
  PD.AddTaggedVal(reinterpret_cast<uint64_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.isFirst() &&
         "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.isFirst() && "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.

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

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

/// OpenMP variants are mangled early based on their OpenMP context selector.
/// The new name looks likes this:
///  <name> + OpenMPVariantManglingSeparatorStr + <mangled OpenMP context>
static constexpr StringRef getOpenMPVariantManglingSeparatorStr() {
  return "$ompvariant";
}

} // namespace clang

#endif // LLVM_CLANG_AST_DECL_H
