//===- Decl.cpp - Declaration AST Node Implementation ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the Decl subclasses.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Decl.h"
#include "Linkage.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CanonicalType.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/ODRHash.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/Sanitizers.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetCXXABI.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Visibility.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>

using namespace clang;

Decl *clang::getPrimaryMergedDecl(Decl *D) {
  return D->getASTContext().getPrimaryMergedDecl(D);
}

void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
  SourceLocation Loc = this->Loc;
  if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();
  if (Loc.isValid()) {
    Loc.print(OS, Context.getSourceManager());
    OS << ": ";
  }
  OS << Message;

  if (auto *ND = dyn_cast_or_null<NamedDecl>(TheDecl)) {
    OS << " '";
    ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
    OS << "'";
  }

  OS << '\n';
}

// Defined here so that it can be inlined into its direct callers.
bool Decl::isOutOfLine() const {
  return !getLexicalDeclContext()->Equals(getDeclContext());
}

TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
    : Decl(TranslationUnit, nullptr, SourceLocation()),
      DeclContext(TranslationUnit), Ctx(ctx) {}

//===----------------------------------------------------------------------===//
// NamedDecl Implementation
//===----------------------------------------------------------------------===//

// Visibility rules aren't rigorously externally specified, but here
// are the basic principles behind what we implement:
//
// 1. An explicit visibility attribute is generally a direct expression
// of the user's intent and should be honored.  Only the innermost
// visibility attribute applies.  If no visibility attribute applies,
// global visibility settings are considered.
//
// 2. There is one caveat to the above: on or in a template pattern,
// an explicit visibility attribute is just a default rule, and
// visibility can be decreased by the visibility of template
// arguments.  But this, too, has an exception: an attribute on an
// explicit specialization or instantiation causes all the visibility
// restrictions of the template arguments to be ignored.
//
// 3. A variable that does not otherwise have explicit visibility can
// be restricted by the visibility of its type.
//
// 4. A visibility restriction is explicit if it comes from an
// attribute (or something like it), not a global visibility setting.
// When emitting a reference to an external symbol, visibility
// restrictions are ignored unless they are explicit.
//
// 5. When computing the visibility of a non-type, including a
// non-type member of a class, only non-type visibility restrictions
// are considered: the 'visibility' attribute, global value-visibility
// settings, and a few special cases like __private_extern.
//
// 6. When computing the visibility of a type, including a type member
// of a class, only type visibility restrictions are considered:
// the 'type_visibility' attribute and global type-visibility settings.
// However, a 'visibility' attribute counts as a 'type_visibility'
// attribute on any declaration that only has the former.
//
// The visibility of a "secondary" entity, like a template argument,
// is computed using the kind of that entity, not the kind of the
// primary entity for which we are computing visibility.  For example,
// the visibility of a specialization of either of these templates:
//   template <class T, bool (&compare)(T, X)> bool has_match(list<T>, X);
//   template <class T, bool (&compare)(T, X)> class matcher;
// is restricted according to the type visibility of the argument 'T',
// the type visibility of 'bool(&)(T,X)', and the value visibility of
// the argument function 'compare'.  That 'has_match' is a value
// and 'matcher' is a type only matters when looking for attributes
// and settings from the immediate context.

/// Does this computation kind permit us to consider additional
/// visibility settings from attributes and the like?
static bool hasExplicitVisibilityAlready(LVComputationKind computation) {
  return computation.IgnoreExplicitVisibility;
}

/// Given an LVComputationKind, return one of the same type/value sort
/// that records that it already has explicit visibility.
static LVComputationKind
withExplicitVisibilityAlready(LVComputationKind Kind) {
  Kind.IgnoreExplicitVisibility = true;
  return Kind;
}

static Optional<Visibility> getExplicitVisibility(const NamedDecl *D,
                                                  LVComputationKind kind) {
  assert(!kind.IgnoreExplicitVisibility &&
         "asking for explicit visibility when we shouldn't be");
  return D->getExplicitVisibility(kind.getExplicitVisibilityKind());
}

/// Is the given declaration a "type" or a "value" for the purposes of
/// visibility computation?
static bool usesTypeVisibility(const NamedDecl *D) {
  return isa<TypeDecl>(D) ||
         isa<ClassTemplateDecl>(D) ||
         isa<ObjCInterfaceDecl>(D);
}

/// Does the given declaration have member specialization information,
/// and if so, is it an explicit specialization?
template <class T> static typename
std::enable_if<!std::is_base_of<RedeclarableTemplateDecl, T>::value, bool>::type
isExplicitMemberSpecialization(const T *D) {
  if (const MemberSpecializationInfo *member =
        D->getMemberSpecializationInfo()) {
    return member->isExplicitSpecialization();
  }
  return false;
}

/// For templates, this question is easier: a member template can't be
/// explicitly instantiated, so there's a single bit indicating whether
/// or not this is an explicit member specialization.
static bool isExplicitMemberSpecialization(const RedeclarableTemplateDecl *D) {
  return D->isMemberSpecialization();
}

/// Given a visibility attribute, return the explicit visibility
/// associated with it.
template <class T>
static Visibility getVisibilityFromAttr(const T *attr) {
  switch (attr->getVisibility()) {
  case T::Default:
    return DefaultVisibility;
  case T::Hidden:
    return HiddenVisibility;
  case T::Protected:
    return ProtectedVisibility;
  }
  llvm_unreachable("bad visibility kind");
}

/// Return the explicit visibility of the given declaration.
static Optional<Visibility> getVisibilityOf(const NamedDecl *D,
                                    NamedDecl::ExplicitVisibilityKind kind) {
  // If we're ultimately computing the visibility of a type, look for
  // a 'type_visibility' attribute before looking for 'visibility'.
  if (kind == NamedDecl::VisibilityForType) {
    if (const auto *A = D->getAttr<TypeVisibilityAttr>()) {
      return getVisibilityFromAttr(A);
    }
  }

  // If this declaration has an explicit visibility attribute, use it.
  if (const auto *A = D->getAttr<VisibilityAttr>()) {
    return getVisibilityFromAttr(A);
  }

  return None;
}

LinkageInfo LinkageComputer::getLVForType(const Type &T,
                                          LVComputationKind computation) {
  if (computation.IgnoreAllVisibility)
    return LinkageInfo(T.getLinkage(), DefaultVisibility, true);
  return getTypeLinkageAndVisibility(&T);
}

/// Get the most restrictive linkage for the types in the given
/// template parameter list.  For visibility purposes, template
/// parameters are part of the signature of a template.
LinkageInfo LinkageComputer::getLVForTemplateParameterList(
    const TemplateParameterList *Params, LVComputationKind computation) {
  LinkageInfo LV;
  for (const NamedDecl *P : *Params) {
    // Template type parameters are the most common and never
    // contribute to visibility, pack or not.
    if (isa<TemplateTypeParmDecl>(P))
      continue;

    // Non-type template parameters can be restricted by the value type, e.g.
    //   template <enum X> class A { ... };
    // We have to be careful here, though, because we can be dealing with
    // dependent types.
    if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
      // Handle the non-pack case first.
      if (!NTTP->isExpandedParameterPack()) {
        if (!NTTP->getType()->isDependentType()) {
          LV.merge(getLVForType(*NTTP->getType(), computation));
        }
        continue;
      }

      // Look at all the types in an expanded pack.
      for (unsigned i = 0, n = NTTP->getNumExpansionTypes(); i != n; ++i) {
        QualType type = NTTP->getExpansionType(i);
        if (!type->isDependentType())
          LV.merge(getTypeLinkageAndVisibility(type));
      }
      continue;
    }

    // Template template parameters can be restricted by their
    // template parameters, recursively.
    const auto *TTP = cast<TemplateTemplateParmDecl>(P);

    // Handle the non-pack case first.
    if (!TTP->isExpandedParameterPack()) {
      LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters(),
                                             computation));
      continue;
    }

    // Look at all expansions in an expanded pack.
    for (unsigned i = 0, n = TTP->getNumExpansionTemplateParameters();
           i != n; ++i) {
      LV.merge(getLVForTemplateParameterList(
          TTP->getExpansionTemplateParameters(i), computation));
    }
  }

  return LV;
}

static const Decl *getOutermostFuncOrBlockContext(const Decl *D) {
  const Decl *Ret = nullptr;
  const DeclContext *DC = D->getDeclContext();
  while (DC->getDeclKind() != Decl::TranslationUnit) {
    if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC))
      Ret = cast<Decl>(DC);
    DC = DC->getParent();
  }
  return Ret;
}

/// Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
///
/// Note that we don't take an LVComputationKind because we always
/// want to honor the visibility of template arguments in the same way.
LinkageInfo
LinkageComputer::getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args,
                                              LVComputationKind computation) {
  LinkageInfo LV;

  for (const TemplateArgument &Arg : Args) {
    switch (Arg.getKind()) {
    case TemplateArgument::Null:
    case TemplateArgument::Integral:
    case TemplateArgument::Expression:
      continue;

    case TemplateArgument::Type:
      LV.merge(getLVForType(*Arg.getAsType(), computation));
      continue;

    case TemplateArgument::Declaration: {
      const NamedDecl *ND = Arg.getAsDecl();
      assert(!usesTypeVisibility(ND));
      LV.merge(getLVForDecl(ND, computation));
      continue;
    }

    case TemplateArgument::NullPtr:
      LV.merge(getTypeLinkageAndVisibility(Arg.getNullPtrType()));
      continue;

    case TemplateArgument::Template:
    case TemplateArgument::TemplateExpansion:
      if (TemplateDecl *Template =
              Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
        LV.merge(getLVForDecl(Template, computation));
      continue;

    case TemplateArgument::Pack:
      LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation));
      continue;
    }
    llvm_unreachable("bad template argument kind");
  }

  return LV;
}

LinkageInfo
LinkageComputer::getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
                                              LVComputationKind computation) {
  return getLVForTemplateArgumentList(TArgs.asArray(), computation);
}

static bool shouldConsiderTemplateVisibility(const FunctionDecl *fn,
                        const FunctionTemplateSpecializationInfo *specInfo) {
  // Include visibility from the template parameters and arguments
  // only if this is not an explicit instantiation or specialization
  // with direct explicit visibility.  (Implicit instantiations won't
  // have a direct attribute.)
  if (!specInfo->isExplicitInstantiationOrSpecialization())
    return true;

  return !fn->hasAttr<VisibilityAttr>();
}

/// Merge in template-related linkage and visibility for the given
/// function template specialization.
///
/// We don't need a computation kind here because we can assume
/// LVForValue.
///
/// \param[out] LV the computation to use for the parent
void LinkageComputer::mergeTemplateLV(
    LinkageInfo &LV, const FunctionDecl *fn,
    const FunctionTemplateSpecializationInfo *specInfo,
    LVComputationKind computation) {
  bool considerVisibility =
    shouldConsiderTemplateVisibility(fn, specInfo);

  // Merge information from the template parameters.
  FunctionTemplateDecl *temp = specInfo->getTemplate();
  LinkageInfo tempLV =
    getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
  LV.mergeMaybeWithVisibility(tempLV, considerVisibility);

  // Merge information from the template arguments.
  const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
  LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
  LV.mergeMaybeWithVisibility(argsLV, considerVisibility);
}

/// Does the given declaration have a direct visibility attribute
/// that would match the given rules?
static bool hasDirectVisibilityAttribute(const NamedDecl *D,
                                         LVComputationKind computation) {
  if (computation.IgnoreAllVisibility)
    return false;

  return (computation.isTypeVisibility() && D->hasAttr<TypeVisibilityAttr>()) ||
         D->hasAttr<VisibilityAttr>();
}

/// Should we consider visibility associated with the template
/// arguments and parameters of the given class template specialization?
static bool shouldConsiderTemplateVisibility(
                                 const ClassTemplateSpecializationDecl *spec,
                                 LVComputationKind computation) {
  // Include visibility from the template parameters and arguments
  // only if this is not an explicit instantiation or specialization
  // with direct explicit visibility (and note that implicit
  // instantiations won't have a direct attribute).
  //
  // Furthermore, we want to ignore template parameters and arguments
  // for an explicit specialization when computing the visibility of a
  // member thereof with explicit visibility.
  //
  // This is a bit complex; let's unpack it.
  //
  // An explicit class specialization is an independent, top-level
  // declaration.  As such, if it or any of its members has an
  // explicit visibility attribute, that must directly express the
  // user's intent, and we should honor it.  The same logic applies to
  // an explicit instantiation of a member of such a thing.

  // Fast path: if this is not an explicit instantiation or
  // specialization, we always want to consider template-related
  // visibility restrictions.
  if (!spec->isExplicitInstantiationOrSpecialization())
    return true;

  // This is the 'member thereof' check.
  if (spec->isExplicitSpecialization() &&
      hasExplicitVisibilityAlready(computation))
    return false;

  return !hasDirectVisibilityAttribute(spec, computation);
}

/// Merge in template-related linkage and visibility for the given
/// class template specialization.
void LinkageComputer::mergeTemplateLV(
    LinkageInfo &LV, const ClassTemplateSpecializationDecl *spec,
    LVComputationKind computation) {
  bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);

  // Merge information from the template parameters, but ignore
  // visibility if we're only considering template arguments.

  ClassTemplateDecl *temp = spec->getSpecializedTemplate();
  LinkageInfo tempLV =
    getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
  LV.mergeMaybeWithVisibility(tempLV,
           considerVisibility && !hasExplicitVisibilityAlready(computation));

  // Merge information from the template arguments.  We ignore
  // template-argument visibility if we've got an explicit
  // instantiation with a visibility attribute.
  const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
  LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
  if (considerVisibility)
    LV.mergeVisibility(argsLV);
  LV.mergeExternalVisibility(argsLV);
}

/// Should we consider visibility associated with the template
/// arguments and parameters of the given variable template
/// specialization? As usual, follow class template specialization
/// logic up to initialization.
static bool shouldConsiderTemplateVisibility(
                                 const VarTemplateSpecializationDecl *spec,
                                 LVComputationKind computation) {
  // Include visibility from the template parameters and arguments
  // only if this is not an explicit instantiation or specialization
  // with direct explicit visibility (and note that implicit
  // instantiations won't have a direct attribute).
  if (!spec->isExplicitInstantiationOrSpecialization())
    return true;

  // An explicit variable specialization is an independent, top-level
  // declaration.  As such, if it has an explicit visibility attribute,
  // that must directly express the user's intent, and we should honor
  // it.
  if (spec->isExplicitSpecialization() &&
      hasExplicitVisibilityAlready(computation))
    return false;

  return !hasDirectVisibilityAttribute(spec, computation);
}

/// Merge in template-related linkage and visibility for the given
/// variable template specialization. As usual, follow class template
/// specialization logic up to initialization.
void LinkageComputer::mergeTemplateLV(LinkageInfo &LV,
                                      const VarTemplateSpecializationDecl *spec,
                                      LVComputationKind computation) {
  bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation);

  // Merge information from the template parameters, but ignore
  // visibility if we're only considering template arguments.

  VarTemplateDecl *temp = spec->getSpecializedTemplate();
  LinkageInfo tempLV =
    getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
  LV.mergeMaybeWithVisibility(tempLV,
           considerVisibility && !hasExplicitVisibilityAlready(computation));

  // Merge information from the template arguments.  We ignore
  // template-argument visibility if we've got an explicit
  // instantiation with a visibility attribute.
  const TemplateArgumentList &templateArgs = spec->getTemplateArgs();
  LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation);
  if (considerVisibility)
    LV.mergeVisibility(argsLV);
  LV.mergeExternalVisibility(argsLV);
}

static bool useInlineVisibilityHidden(const NamedDecl *D) {
  // FIXME: we should warn if -fvisibility-inlines-hidden is used with c.
  const LangOptions &Opts = D->getASTContext().getLangOpts();
  if (!Opts.CPlusPlus || !Opts.InlineVisibilityHidden)
    return false;

  const auto *FD = dyn_cast<FunctionDecl>(D);
  if (!FD)
    return false;

  TemplateSpecializationKind TSK = TSK_Undeclared;
  if (FunctionTemplateSpecializationInfo *spec
      = FD->getTemplateSpecializationInfo()) {
    TSK = spec->getTemplateSpecializationKind();
  } else if (MemberSpecializationInfo *MSI =
             FD->getMemberSpecializationInfo()) {
    TSK = MSI->getTemplateSpecializationKind();
  }

  const FunctionDecl *Def = nullptr;
  // InlineVisibilityHidden only applies to definitions, and
  // isInlined() only gives meaningful answers on definitions
  // anyway.
  return TSK != TSK_ExplicitInstantiationDeclaration &&
    TSK != TSK_ExplicitInstantiationDefinition &&
    FD->hasBody(Def) && Def->isInlined() && !Def->hasAttr<GNUInlineAttr>();
}

template <typename T> static bool isFirstInExternCContext(T *D) {
  const T *First = D->getFirstDecl();
  return First->isInExternCContext();
}

static bool isSingleLineLanguageLinkage(const Decl &D) {
  if (const auto *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext()))
    if (!SD->hasBraces())
      return true;
  return false;
}

/// Determine whether D is declared in the purview of a named module.
static bool isInModulePurview(const NamedDecl *D) {
  if (auto *M = D->getOwningModule())
    return M->isModulePurview();
  return false;
}

static bool isExportedFromModuleInterfaceUnit(const NamedDecl *D) {
  // FIXME: Handle isModulePrivate.
  switch (D->getModuleOwnershipKind()) {
  case Decl::ModuleOwnershipKind::Unowned:
  case Decl::ModuleOwnershipKind::ModulePrivate:
    return false;
  case Decl::ModuleOwnershipKind::Visible:
  case Decl::ModuleOwnershipKind::VisibleWhenImported:
    return isInModulePurview(D);
  }
  llvm_unreachable("unexpected module ownership kind");
}

static LinkageInfo getInternalLinkageFor(const NamedDecl *D) {
  // Internal linkage declarations within a module interface unit are modeled
  // as "module-internal linkage", which means that they have internal linkage
  // formally but can be indirectly accessed from outside the module via inline
  // functions and templates defined within the module.
  if (isInModulePurview(D))
    return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false);

  return LinkageInfo::internal();
}

static LinkageInfo getExternalLinkageFor(const NamedDecl *D) {
  // C++ Modules TS [basic.link]/6.8:
  //   - A name declared at namespace scope that does not have internal linkage
  //     by the previous rules and that is introduced by a non-exported
  //     declaration has module linkage.
  if (isInModulePurview(D) && !isExportedFromModuleInterfaceUnit(
                                  cast<NamedDecl>(D->getCanonicalDecl())))
    return LinkageInfo(ModuleLinkage, DefaultVisibility, false);

  return LinkageInfo::external();
}

static StorageClass getStorageClass(const Decl *D) {
  if (auto *TD = dyn_cast<TemplateDecl>(D))
    D = TD->getTemplatedDecl();
  if (D) {
    if (auto *VD = dyn_cast<VarDecl>(D))
      return VD->getStorageClass();
    if (auto *FD = dyn_cast<FunctionDecl>(D))
      return FD->getStorageClass();
  }
  return SC_None;
}

LinkageInfo
LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
                                            LVComputationKind computation,
                                            bool IgnoreVarTypeLinkage) {
  assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
         "Not a name having namespace scope");
  ASTContext &Context = D->getASTContext();

  // C++ [basic.link]p3:
  //   A name having namespace scope (3.3.6) has internal linkage if it
  //   is the name of

  if (getStorageClass(D->getCanonicalDecl()) == SC_Static) {
    // - a variable, variable template, function, or function template
    //   that is explicitly declared static; or
    // (This bullet corresponds to C99 6.2.2p3.)
    return getInternalLinkageFor(D);
  }

  if (const auto *Var = dyn_cast<VarDecl>(D)) {
    // - a non-template variable of non-volatile const-qualified type, unless
    //   - it is explicitly declared extern, or
    //   - it is inline or exported, or
    //   - it was previously declared and the prior declaration did not have
    //     internal linkage
    // (There is no equivalent in C99.)
    if (Context.getLangOpts().CPlusPlus &&
        Var->getType().isConstQualified() &&
        !Var->getType().isVolatileQualified() &&
        !Var->isInline() &&
        !isExportedFromModuleInterfaceUnit(Var) &&
        !isa<VarTemplateSpecializationDecl>(Var) &&
        !Var->getDescribedVarTemplate()) {
      const VarDecl *PrevVar = Var->getPreviousDecl();
      if (PrevVar)
        return getLVForDecl(PrevVar, computation);

      if (Var->getStorageClass() != SC_Extern &&
          Var->getStorageClass() != SC_PrivateExtern &&
          !isSingleLineLanguageLinkage(*Var))
        return getInternalLinkageFor(Var);
    }

    for (const VarDecl *PrevVar = Var->getPreviousDecl(); PrevVar;
         PrevVar = PrevVar->getPreviousDecl()) {
      if (PrevVar->getStorageClass() == SC_PrivateExtern &&
          Var->getStorageClass() == SC_None)
        return getDeclLinkageAndVisibility(PrevVar);
      // Explicitly declared static.
      if (PrevVar->getStorageClass() == SC_Static)
        return getInternalLinkageFor(Var);
    }
  } else if (const auto *IFD = dyn_cast<IndirectFieldDecl>(D)) {
    //   - a data member of an anonymous union.
    const VarDecl *VD = IFD->getVarDecl();
    assert(VD && "Expected a VarDecl in this IndirectFieldDecl!");
    return getLVForNamespaceScopeDecl(VD, computation, IgnoreVarTypeLinkage);
  }
  assert(!isa<FieldDecl>(D) && "Didn't expect a FieldDecl!");

  // FIXME: This gives internal linkage to names that should have no linkage
  // (those not covered by [basic.link]p6).
  if (D->isInAnonymousNamespace()) {
    const auto *Var = dyn_cast<VarDecl>(D);
    const auto *Func = dyn_cast<FunctionDecl>(D);
    // FIXME: The check for extern "C" here is not justified by the standard
    // wording, but we retain it from the pre-DR1113 model to avoid breaking
    // code.
    //
    // C++11 [basic.link]p4:
    //   An unnamed namespace or a namespace declared directly or indirectly
    //   within an unnamed namespace has internal linkage.
    if ((!Var || !isFirstInExternCContext(Var)) &&
        (!Func || !isFirstInExternCContext(Func)))
      return getInternalLinkageFor(D);
  }

  // Set up the defaults.

  // C99 6.2.2p5:
  //   If the declaration of an identifier for an object has file
  //   scope and no storage-class specifier, its linkage is
  //   external.
  LinkageInfo LV = getExternalLinkageFor(D);

  if (!hasExplicitVisibilityAlready(computation)) {
    if (Optional<Visibility> Vis = getExplicitVisibility(D, computation)) {
      LV.mergeVisibility(*Vis, true);
    } else {
      // If we're declared in a namespace with a visibility attribute,
      // use that namespace's visibility, and it still counts as explicit.
      for (const DeclContext *DC = D->getDeclContext();
           !isa<TranslationUnitDecl>(DC);
           DC = DC->getParent()) {
        const auto *ND = dyn_cast<NamespaceDecl>(DC);
        if (!ND) continue;
        if (Optional<Visibility> Vis = getExplicitVisibility(ND, computation)) {
          LV.mergeVisibility(*Vis, true);
          break;
        }
      }
    }

    // Add in global settings if the above didn't give us direct visibility.
    if (!LV.isVisibilityExplicit()) {
      // Use global type/value visibility as appropriate.
      Visibility globalVisibility =
          computation.isValueVisibility()
              ? Context.getLangOpts().getValueVisibilityMode()
              : Context.getLangOpts().getTypeVisibilityMode();
      LV.mergeVisibility(globalVisibility, /*explicit*/ false);

      // If we're paying attention to global visibility, apply
      // -finline-visibility-hidden if this is an inline method.
      if (useInlineVisibilityHidden(D))
        LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
    }
  }

  // C++ [basic.link]p4:

  //   A name having namespace scope that has not been given internal linkage
  //   above and that is the name of
  //   [...bullets...]
  //   has its linkage determined as follows:
  //     - if the enclosing namespace has internal linkage, the name has
  //       internal linkage; [handled above]
  //     - otherwise, if the declaration of the name is attached to a named
  //       module and is not exported, the name has module linkage;
  //     - otherwise, the name has external linkage.
  // LV is currently set up to handle the last two bullets.
  //
  //   The bullets are:

  //     - a variable; or
  if (const auto *Var = dyn_cast<VarDecl>(D)) {
    // GCC applies the following optimization to variables and static
    // data members, but not to functions:
    //
    // Modify the variable's LV by the LV of its type unless this is
    // C or extern "C".  This follows from [basic.link]p9:
    //   A type without linkage shall not be used as the type of a
    //   variable or function with external linkage unless
    //    - the entity has C language linkage, or
    //    - the entity is declared within an unnamed namespace, or
    //    - the entity is not used or is defined in the same
    //      translation unit.
    // and [basic.link]p10:
    //   ...the types specified by all declarations referring to a
    //   given variable or function shall be identical...
    // C does not have an equivalent rule.
    //
    // Ignore this if we've got an explicit attribute;  the user
    // probably knows what they're doing.
    //
    // Note that we don't want to make the variable non-external
    // because of this, but unique-external linkage suits us.
    if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var) &&
        !IgnoreVarTypeLinkage) {
      LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
      if (!isExternallyVisible(TypeLV.getLinkage()))
        return LinkageInfo::uniqueExternal();
      if (!LV.isVisibilityExplicit())
        LV.mergeVisibility(TypeLV);
    }

    if (Var->getStorageClass() == SC_PrivateExtern)
      LV.mergeVisibility(HiddenVisibility, true);

    // Note that Sema::MergeVarDecl already takes care of implementing
    // C99 6.2.2p4 and propagating the visibility attribute, so we don't have
    // to do it here.

    // As per function and class template specializations (below),
    // consider LV for the template and template arguments.  We're at file
    // scope, so we do not need to worry about nested specializations.
    if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(Var)) {
      mergeTemplateLV(LV, spec, computation);
    }

  //     - a function; or
  } else if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
    // In theory, we can modify the function's LV by the LV of its
    // type unless it has C linkage (see comment above about variables
    // for justification).  In practice, GCC doesn't do this, so it's
    // just too painful to make work.

    if (Function->getStorageClass() == SC_PrivateExtern)
      LV.mergeVisibility(HiddenVisibility, true);

    // Note that Sema::MergeCompatibleFunctionDecls already takes care of
    // merging storage classes and visibility attributes, so we don't have to
    // look at previous decls in here.

    // In C++, then if the type of the function uses a type with
    // unique-external linkage, it's not legally usable from outside
    // this translation unit.  However, we should use the C linkage
    // rules instead for extern "C" declarations.
    if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Function)) {
      // Only look at the type-as-written. Otherwise, deducing the return type
      // of a function could change its linkage.
      QualType TypeAsWritten = Function->getType();
      if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
        TypeAsWritten = TSI->getType();
      if (!isExternallyVisible(TypeAsWritten->getLinkage()))
        return LinkageInfo::uniqueExternal();
    }

    // Consider LV from the template and the template arguments.
    // We're at file scope, so we do not need to worry about nested
    // specializations.
    if (FunctionTemplateSpecializationInfo *specInfo
                               = Function->getTemplateSpecializationInfo()) {
      mergeTemplateLV(LV, Function, specInfo, computation);
    }

  //     - a named class (Clause 9), or an unnamed class defined in a
  //       typedef declaration in which the class has the typedef name
  //       for linkage purposes (7.1.3); or
  //     - a named enumeration (7.2), or an unnamed enumeration
  //       defined in a typedef declaration in which the enumeration
  //       has the typedef name for linkage purposes (7.1.3); or
  } else if (const auto *Tag = dyn_cast<TagDecl>(D)) {
    // Unnamed tags have no linkage.
    if (!Tag->hasNameForLinkage())
      return LinkageInfo::none();

    // If this is a class template specialization, consider the
    // linkage of the template and template arguments.  We're at file
    // scope, so we do not need to worry about nested specializations.
    if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
      mergeTemplateLV(LV, spec, computation);
    }

  // FIXME: This is not part of the C++ standard any more.
  //     - an enumerator belonging to an enumeration with external linkage; or
  } else if (isa<EnumConstantDecl>(D)) {
    LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()),
                                      computation);
    if (!isExternalFormalLinkage(EnumLV.getLinkage()))
      return LinkageInfo::none();
    LV.merge(EnumLV);

  //     - a template
  } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
    bool considerVisibility = !hasExplicitVisibilityAlready(computation);
    LinkageInfo tempLV =
      getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
    LV.mergeMaybeWithVisibility(tempLV, considerVisibility);

  //     An unnamed namespace or a namespace declared directly or indirectly
  //     within an unnamed namespace has internal linkage. All other namespaces
  //     have external linkage.
  //
  // We handled names in anonymous namespaces above.
  } else if (isa<NamespaceDecl>(D)) {
    return LV;

  // By extension, we assign external linkage to Objective-C
  // interfaces.
  } else if (isa<ObjCInterfaceDecl>(D)) {
    // fallout

  } else if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
    // A typedef declaration has linkage if it gives a type a name for
    // linkage purposes.
    if (!TD->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
      return LinkageInfo::none();

  } else if (isa<MSGuidDecl>(D)) {
    // A GUID behaves like an inline variable with external linkage. Fall
    // through.

  // Everything not covered here has no linkage.
  } else {
    return LinkageInfo::none();
  }

  // If we ended up with non-externally-visible linkage, visibility should
  // always be default.
  if (!isExternallyVisible(LV.getLinkage()))
    return LinkageInfo(LV.getLinkage(), DefaultVisibility, false);

  // Mark the symbols as hidden when compiling for the device.
  if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice)
    LV.mergeVisibility(HiddenVisibility, /*newExplicit=*/false);

  return LV;
}

LinkageInfo
LinkageComputer::getLVForClassMember(const NamedDecl *D,
                                     LVComputationKind computation,
                                     bool IgnoreVarTypeLinkage) {
  // Only certain class members have linkage.  Note that fields don't
  // really have linkage, but it's convenient to say they do for the
  // purposes of calculating linkage of pointer-to-data-member
  // template arguments.
  //
  // Templates also don't officially have linkage, but since we ignore
  // the C++ standard and look at template arguments when determining
  // linkage and visibility of a template specialization, we might hit
  // a template template argument that way. If we do, we need to
  // consider its linkage.
  if (!(isa<CXXMethodDecl>(D) ||
        isa<VarDecl>(D) ||
        isa<FieldDecl>(D) ||
        isa<IndirectFieldDecl>(D) ||
        isa<TagDecl>(D) ||
        isa<TemplateDecl>(D)))
    return LinkageInfo::none();

  LinkageInfo LV;

  // If we have an explicit visibility attribute, merge that in.
  if (!hasExplicitVisibilityAlready(computation)) {
    if (Optional<Visibility> Vis = getExplicitVisibility(D, computation))
      LV.mergeVisibility(*Vis, true);
    // If we're paying attention to global visibility, apply
    // -finline-visibility-hidden if this is an inline method.
    //
    // Note that we do this before merging information about
    // the class visibility.
    if (!LV.isVisibilityExplicit() && useInlineVisibilityHidden(D))
      LV.mergeVisibility(HiddenVisibility, /*visibilityExplicit=*/false);
  }

  // If this class member has an explicit visibility attribute, the only
  // thing that can change its visibility is the template arguments, so
  // only look for them when processing the class.
  LVComputationKind classComputation = computation;
  if (LV.isVisibilityExplicit())
    classComputation = withExplicitVisibilityAlready(computation);

  LinkageInfo classLV =
    getLVForDecl(cast<RecordDecl>(D->getDeclContext()), classComputation);
  // The member has the same linkage as the class. If that's not externally
  // visible, we don't need to compute anything about the linkage.
  // FIXME: If we're only computing linkage, can we bail out here?
  if (!isExternallyVisible(classLV.getLinkage()))
    return classLV;


  // Otherwise, don't merge in classLV yet, because in certain cases
  // we need to completely ignore the visibility from it.

  // Specifically, if this decl exists and has an explicit attribute.
  const NamedDecl *explicitSpecSuppressor = nullptr;

  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
    // Only look at the type-as-written. Otherwise, deducing the return type
    // of a function could change its linkage.
    QualType TypeAsWritten = MD->getType();
    if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
      TypeAsWritten = TSI->getType();
    if (!isExternallyVisible(TypeAsWritten->getLinkage()))
      return LinkageInfo::uniqueExternal();

    // If this is a method template specialization, use the linkage for
    // the template parameters and arguments.
    if (FunctionTemplateSpecializationInfo *spec
           = MD->getTemplateSpecializationInfo()) {
      mergeTemplateLV(LV, MD, spec, computation);
      if (spec->isExplicitSpecialization()) {
        explicitSpecSuppressor = MD;
      } else if (isExplicitMemberSpecialization(spec->getTemplate())) {
        explicitSpecSuppressor = spec->getTemplate()->getTemplatedDecl();
      }
    } else if (isExplicitMemberSpecialization(MD)) {
      explicitSpecSuppressor = MD;
    }

  } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
    if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
      mergeTemplateLV(LV, spec, computation);
      if (spec->isExplicitSpecialization()) {
        explicitSpecSuppressor = spec;
      } else {
        const ClassTemplateDecl *temp = spec->getSpecializedTemplate();
        if (isExplicitMemberSpecialization(temp)) {
          explicitSpecSuppressor = temp->getTemplatedDecl();
        }
      }
    } else if (isExplicitMemberSpecialization(RD)) {
      explicitSpecSuppressor = RD;
    }

  // Static data members.
  } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
    if (const auto *spec = dyn_cast<VarTemplateSpecializationDecl>(VD))
      mergeTemplateLV(LV, spec, computation);

    // Modify the variable's linkage by its type, but ignore the
    // type's visibility unless it's a definition.
    if (!IgnoreVarTypeLinkage) {
      LinkageInfo typeLV = getLVForType(*VD->getType(), computation);
      // FIXME: If the type's linkage is not externally visible, we can
      // give this static data member UniqueExternalLinkage.
      if (!LV.isVisibilityExplicit() && !classLV.isVisibilityExplicit())
        LV.mergeVisibility(typeLV);
      LV.mergeExternalVisibility(typeLV);
    }

    if (isExplicitMemberSpecialization(VD)) {
      explicitSpecSuppressor = VD;
    }

  // Template members.
  } else if (const auto *temp = dyn_cast<TemplateDecl>(D)) {
    bool considerVisibility =
      (!LV.isVisibilityExplicit() &&
       !classLV.isVisibilityExplicit() &&
       !hasExplicitVisibilityAlready(computation));
    LinkageInfo tempLV =
      getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
    LV.mergeMaybeWithVisibility(tempLV, considerVisibility);

    if (const auto *redeclTemp = dyn_cast<RedeclarableTemplateDecl>(temp)) {
      if (isExplicitMemberSpecialization(redeclTemp)) {
        explicitSpecSuppressor = temp->getTemplatedDecl();
      }
    }
  }

  // We should never be looking for an attribute directly on a template.
  assert(!explicitSpecSuppressor || !isa<TemplateDecl>(explicitSpecSuppressor));

  // If this member is an explicit member specialization, and it has
  // an explicit attribute, ignore visibility from the parent.
  bool considerClassVisibility = true;
  if (explicitSpecSuppressor &&
      // optimization: hasDVA() is true only with explicit visibility.
      LV.isVisibilityExplicit() &&
      classLV.getVisibility() != DefaultVisibility &&
      hasDirectVisibilityAttribute(explicitSpecSuppressor, computation)) {
    considerClassVisibility = false;
  }

  // Finally, merge in information from the class.
  LV.mergeMaybeWithVisibility(classLV, considerClassVisibility);
  return LV;
}

void NamedDecl::anchor() {}

bool NamedDecl::isLinkageValid() const {
  if (!hasCachedLinkage())
    return true;

  Linkage L = LinkageComputer{}
                  .computeLVForDecl(this, LVComputationKind::forLinkageOnly())
                  .getLinkage();
  return L == getCachedLinkage();
}

ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
  StringRef name = getName();
  if (name.empty()) return SFF_None;

  if (name.front() == 'C')
    if (name == "CFStringCreateWithFormat" ||
        name == "CFStringCreateWithFormatAndArguments" ||
        name == "CFStringAppendFormat" ||
        name == "CFStringAppendFormatAndArguments")
      return SFF_CFString;
  return SFF_None;
}

Linkage NamedDecl::getLinkageInternal() const {
  // We don't care about visibility here, so ask for the cheapest
  // possible visibility analysis.
  return LinkageComputer{}
      .getLVForDecl(this, LVComputationKind::forLinkageOnly())
      .getLinkage();
}

LinkageInfo NamedDecl::getLinkageAndVisibility() const {
  return LinkageComputer{}.getDeclLinkageAndVisibility(this);
}

static Optional<Visibility>
getExplicitVisibilityAux(const NamedDecl *ND,
                         NamedDecl::ExplicitVisibilityKind kind,
                         bool IsMostRecent) {
  assert(!IsMostRecent || ND == ND->getMostRecentDecl());

  // Check the declaration itself first.
  if (Optional<Visibility> V = getVisibilityOf(ND, kind))
    return V;

  // If this is a member class of a specialization of a class template
  // and the corresponding decl has explicit visibility, use that.
  if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
    CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
    if (InstantiatedFrom)
      return getVisibilityOf(InstantiatedFrom, kind);
  }

  // If there wasn't explicit visibility there, and this is a
  // specialization of a class template, check for visibility
  // on the pattern.
  if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
    // Walk all the template decl till this point to see if there are
    // explicit visibility attributes.
    const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl();
    while (TD != nullptr) {
      auto Vis = getVisibilityOf(TD, kind);
      if (Vis != None)
        return Vis;
      TD = TD->getPreviousDecl();
    }
    return None;
  }

  // Use the most recent declaration.
  if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
    const NamedDecl *MostRecent = ND->getMostRecentDecl();
    if (MostRecent != ND)
      return getExplicitVisibilityAux(MostRecent, kind, true);
  }

  if (const auto *Var = dyn_cast<VarDecl>(ND)) {
    if (Var->isStaticDataMember()) {
      VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
      if (InstantiatedFrom)
        return getVisibilityOf(InstantiatedFrom, kind);
    }

    if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Var))
      return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(),
                             kind);

    return None;
  }
  // Also handle function template specializations.
  if (const auto *fn = dyn_cast<FunctionDecl>(ND)) {
    // If the function is a specialization of a template with an
    // explicit visibility attribute, use that.
    if (FunctionTemplateSpecializationInfo *templateInfo
          = fn->getTemplateSpecializationInfo())
      return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
                             kind);

    // If the function is a member of a specialization of a class template
    // and the corresponding decl has explicit visibility, use that.
    FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
    if (InstantiatedFrom)
      return getVisibilityOf(InstantiatedFrom, kind);

    return None;
  }

  // The visibility of a template is stored in the templated decl.
  if (const auto *TD = dyn_cast<TemplateDecl>(ND))
    return getVisibilityOf(TD->getTemplatedDecl(), kind);

  return None;
}

Optional<Visibility>
NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
  return getExplicitVisibilityAux(this, kind, false);
}

LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
                                             Decl *ContextDecl,
                                             LVComputationKind computation) {
  // This lambda has its linkage/visibility determined by its owner.
  const NamedDecl *Owner;
  if (!ContextDecl)
    Owner = dyn_cast<NamedDecl>(DC);
  else if (isa<ParmVarDecl>(ContextDecl))
    Owner =
        dyn_cast<NamedDecl>(ContextDecl->getDeclContext()->getRedeclContext());
  else
    Owner = cast<NamedDecl>(ContextDecl);

  if (!Owner)
    return LinkageInfo::none();

  // If the owner has a deduced type, we need to skip querying the linkage and
  // visibility of that type, because it might involve this closure type.  The
  // only effect of this is that we might give a lambda VisibleNoLinkage rather
  // than NoLinkage when we don't strictly need to, which is benign.
  auto *VD = dyn_cast<VarDecl>(Owner);
  LinkageInfo OwnerLV =
      VD && VD->getType()->getContainedDeducedType()
          ? computeLVForDecl(Owner, computation, /*IgnoreVarTypeLinkage*/true)
          : getLVForDecl(Owner, computation);

  // A lambda never formally has linkage. But if the owner is externally
  // visible, then the lambda is too. We apply the same rules to blocks.
  if (!isExternallyVisible(OwnerLV.getLinkage()))
    return LinkageInfo::none();
  return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(),
                     OwnerLV.isVisibilityExplicit());
}

LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
                                               LVComputationKind computation) {
  if (const auto *Function = dyn_cast<FunctionDecl>(D)) {
    if (Function->isInAnonymousNamespace() &&
        !isFirstInExternCContext(Function))
      return getInternalLinkageFor(Function);

    // This is a "void f();" which got merged with a file static.
    if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
      return getInternalLinkageFor(Function);

    LinkageInfo LV;
    if (!hasExplicitVisibilityAlready(computation)) {
      if (Optional<Visibility> Vis =
              getExplicitVisibility(Function, computation))
        LV.mergeVisibility(*Vis, true);
    }

    // Note that Sema::MergeCompatibleFunctionDecls already takes care of
    // merging storage classes and visibility attributes, so we don't have to
    // look at previous decls in here.

    return LV;
  }

  if (const auto *Var = dyn_cast<VarDecl>(D)) {
    if (Var->hasExternalStorage()) {
      if (Var->isInAnonymousNamespace() && !isFirstInExternCContext(Var))
        return getInternalLinkageFor(Var);

      LinkageInfo LV;
      if (Var->getStorageClass() == SC_PrivateExtern)
        LV.mergeVisibility(HiddenVisibility, true);
      else if (!hasExplicitVisibilityAlready(computation)) {
        if (Optional<Visibility> Vis = getExplicitVisibility(Var, computation))
          LV.mergeVisibility(*Vis, true);
      }

      if (const VarDecl *Prev = Var->getPreviousDecl()) {
        LinkageInfo PrevLV = getLVForDecl(Prev, computation);
        if (PrevLV.getLinkage())
          LV.setLinkage(PrevLV.getLinkage());
        LV.mergeVisibility(PrevLV);
      }

      return LV;
    }

    if (!Var->isStaticLocal())
      return LinkageInfo::none();
  }

  ASTContext &Context = D->getASTContext();
  if (!Context.getLangOpts().CPlusPlus)
    return LinkageInfo::none();

  const Decl *OuterD = getOutermostFuncOrBlockContext(D);
  if (!OuterD || OuterD->isInvalidDecl())
    return LinkageInfo::none();

  LinkageInfo LV;
  if (const auto *BD = dyn_cast<BlockDecl>(OuterD)) {
    if (!BD->getBlockManglingNumber())
      return LinkageInfo::none();

    LV = getLVForClosure(BD->getDeclContext()->getRedeclContext(),
                         BD->getBlockManglingContextDecl(), computation);
  } else {
    const auto *FD = cast<FunctionDecl>(OuterD);
    if (!FD->isInlined() &&
        !isTemplateInstantiation(FD->getTemplateSpecializationKind()))
      return LinkageInfo::none();

    // If a function is hidden by -fvisibility-inlines-hidden option and
    // is not explicitly attributed as a hidden function,
    // we should not make static local variables in the function hidden.
    LV = getLVForDecl(FD, computation);
    if (isa<VarDecl>(D) && useInlineVisibilityHidden(FD) &&
        !LV.isVisibilityExplicit()) {
      assert(cast<VarDecl>(D)->isStaticLocal());
      // If this was an implicitly hidden inline method, check again for
      // explicit visibility on the parent class, and use that for static locals
      // if present.
      if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
        LV = getLVForDecl(MD->getParent(), computation);
      if (!LV.isVisibilityExplicit()) {
        Visibility globalVisibility =
            computation.isValueVisibility()
                ? Context.getLangOpts().getValueVisibilityMode()
                : Context.getLangOpts().getTypeVisibilityMode();
        return LinkageInfo(VisibleNoLinkage, globalVisibility,
                           /*visibilityExplicit=*/false);
      }
    }
  }
  if (!isExternallyVisible(LV.getLinkage()))
    return LinkageInfo::none();
  return LinkageInfo(VisibleNoLinkage, LV.getVisibility(),
                     LV.isVisibilityExplicit());
}

LinkageInfo LinkageComputer::computeLVForDecl(const NamedDecl *D,
                                              LVComputationKind computation,
                                              bool IgnoreVarTypeLinkage) {
  // Internal_linkage attribute overrides other considerations.
  if (D->hasAttr<InternalLinkageAttr>())
    return getInternalLinkageFor(D);

  // Objective-C: treat all Objective-C declarations as having external
  // linkage.
  switch (D->getKind()) {
    default:
      break;

    // Per C++ [basic.link]p2, only the names of objects, references,
    // functions, types, templates, namespaces, and values ever have linkage.
    //
    // Note that the name of a typedef, namespace alias, using declaration,
    // and so on are not the name of the corresponding type, namespace, or
    // declaration, so they do *not* have linkage.
    case Decl::ImplicitParam:
    case Decl::Label:
    case Decl::NamespaceAlias:
    case Decl::ParmVar:
    case Decl::Using:
    case Decl::UsingShadow:
    case Decl::UsingDirective:
      return LinkageInfo::none();

    case Decl::EnumConstant:
      // C++ [basic.link]p4: an enumerator has the linkage of its enumeration.
      if (D->getASTContext().getLangOpts().CPlusPlus)
        return getLVForDecl(cast<EnumDecl>(D->getDeclContext()), computation);
      return LinkageInfo::visible_none();

    case Decl::Typedef:
    case Decl::TypeAlias:
      // A typedef declaration has linkage if it gives a type a name for
      // linkage purposes.
      if (!cast<TypedefNameDecl>(D)
               ->getAnonDeclWithTypedefName(/*AnyRedecl*/true))
        return LinkageInfo::none();
      break;

    case Decl::TemplateTemplateParm: // count these as external
    case Decl::NonTypeTemplateParm:
    case Decl::ObjCAtDefsField:
    case Decl::ObjCCategory:
    case Decl::ObjCCategoryImpl:
    case Decl::ObjCCompatibleAlias:
    case Decl::ObjCImplementation:
    case Decl::ObjCMethod:
    case Decl::ObjCProperty:
    case Decl::ObjCPropertyImpl:
    case Decl::ObjCProtocol:
      return getExternalLinkageFor(D);

    case Decl::CXXRecord: {
      const auto *Record = cast<CXXRecordDecl>(D);
      if (Record->isLambda()) {
        if (Record->hasKnownLambdaInternalLinkage() ||
            !Record->getLambdaManglingNumber()) {
          // This lambda has no mangling number, so it's internal.
          return getInternalLinkageFor(D);
        }

        return getLVForClosure(
                  Record->getDeclContext()->getRedeclContext(),
                  Record->getLambdaContextDecl(), computation);
      }

      break;
    }
  }

  // Handle linkage for namespace-scope names.
  if (D->getDeclContext()->getRedeclContext()->isFileContext())
    return getLVForNamespaceScopeDecl(D, computation, IgnoreVarTypeLinkage);

  // C++ [basic.link]p5:
  //   In addition, a member function, static data member, a named
  //   class or enumeration of class scope, or an unnamed class or
  //   enumeration defined in a class-scope typedef declaration such
  //   that the class or enumeration has the typedef name for linkage
  //   purposes (7.1.3), has external linkage if the name of the class
  //   has external linkage.
  if (D->getDeclContext()->isRecord())
    return getLVForClassMember(D, computation, IgnoreVarTypeLinkage);

  // C++ [basic.link]p6:
  //   The name of a function declared in block scope and the name of
  //   an object declared by a block scope extern declaration have
  //   linkage. If there is a visible declaration of an entity with
  //   linkage having the same name and type, ignoring entities
  //   declared outside the innermost enclosing namespace scope, the
  //   block scope declaration declares that same entity and receives
  //   the linkage of the previous declaration. If there is more than
  //   one such matching entity, the program is ill-formed. Otherwise,
  //   if no matching entity is found, the block scope entity receives
  //   external linkage.
  if (D->getDeclContext()->isFunctionOrMethod())
    return getLVForLocalDecl(D, computation);

  // C++ [basic.link]p6:
  //   Names not covered by these rules have no linkage.
  return LinkageInfo::none();
}

/// getLVForDecl - Get the linkage and visibility for the given declaration.
LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
                                          LVComputationKind computation) {
  // Internal_linkage attribute overrides other considerations.
  if (D->hasAttr<InternalLinkageAttr>())
    return getInternalLinkageFor(D);

  if (computation.IgnoreAllVisibility && D->hasCachedLinkage())
    return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);

  if (llvm::Optional<LinkageInfo> LI = lookup(D, computation))
    return *LI;

  LinkageInfo LV = computeLVForDecl(D, computation);
  if (D->hasCachedLinkage())
    assert(D->getCachedLinkage() == LV.getLinkage());

  D->setCachedLinkage(LV.getLinkage());
  cache(D, computation, LV);

#ifndef NDEBUG
  // In C (because of gnu inline) and in c++ with microsoft extensions an
  // static can follow an extern, so we can have two decls with different
  // linkages.
  const LangOptions &Opts = D->getASTContext().getLangOpts();
  if (!Opts.CPlusPlus || Opts.MicrosoftExt)
    return LV;

  // We have just computed the linkage for this decl. By induction we know
  // that all other computed linkages match, check that the one we just
  // computed also does.
  NamedDecl *Old = nullptr;
  for (auto I : D->redecls()) {
    auto *T = cast<NamedDecl>(I);
    if (T == D)
      continue;
    if (!T->isInvalidDecl() && T->hasCachedLinkage()) {
      Old = T;
      break;
    }
  }
  assert(!Old || Old->getCachedLinkage() == D->getCachedLinkage());
#endif

  return LV;
}

LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
  return getLVForDecl(D,
                      LVComputationKind(usesTypeVisibility(D)
                                            ? NamedDecl::VisibilityForType
                                            : NamedDecl::VisibilityForValue));
}

Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
  Module *M = getOwningModule();
  if (!M)
    return nullptr;

  switch (M->Kind) {
  case Module::ModuleMapModule:
    // Module map modules have no special linkage semantics.
    return nullptr;

  case Module::ModuleInterfaceUnit:
    return M;

  case Module::GlobalModuleFragment: {
    // External linkage declarations in the global module have no owning module
    // for linkage purposes. But internal linkage declarations in the global
    // module fragment of a particular module are owned by that module for
    // linkage purposes.
    if (IgnoreLinkage)
      return nullptr;
    bool InternalLinkage;
    if (auto *ND = dyn_cast<NamedDecl>(this))
      InternalLinkage = !ND->hasExternalFormalLinkage();
    else {
      auto *NSD = dyn_cast<NamespaceDecl>(this);
      InternalLinkage = (NSD && NSD->isAnonymousNamespace()) ||
                        isInAnonymousNamespace();
    }
    return InternalLinkage ? M->Parent : nullptr;
  }

  case Module::PrivateModuleFragment:
    // The private module fragment is part of its containing module for linkage
    // purposes.
    return M->Parent;
  }

  llvm_unreachable("unknown module kind");
}

void NamedDecl::printName(raw_ostream &os) const {
  os << Name;
}

std::string NamedDecl::getQualifiedNameAsString() const {
  std::string QualName;
  llvm::raw_string_ostream OS(QualName);
  printQualifiedName(OS, getASTContext().getPrintingPolicy());
  return OS.str();
}

void NamedDecl::printQualifiedName(raw_ostream &OS) const {
  printQualifiedName(OS, getASTContext().getPrintingPolicy());
}

void NamedDecl::printQualifiedName(raw_ostream &OS,
                                   const PrintingPolicy &P) const {
  if (getDeclContext()->isFunctionOrMethod()) {
    // We do not print '(anonymous)' for function parameters without name.
    printName(OS);
    return;
  }
  printNestedNameSpecifier(OS, P);
  if (getDeclName())
    OS << *this;
  else {
    // Give the printName override a chance to pick a different name before we
    // fall back to "(anonymous)".
    SmallString<64> NameBuffer;
    llvm::raw_svector_ostream NameOS(NameBuffer);
    printName(NameOS);
    if (NameBuffer.empty())
      OS << "(anonymous)";
    else
      OS << NameBuffer;
  }
}

void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const {
  printNestedNameSpecifier(OS, getASTContext().getPrintingPolicy());
}

void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
                                         const PrintingPolicy &P) const {
  const DeclContext *Ctx = getDeclContext();

  // For ObjC methods and properties, look through categories and use the
  // interface as context.
  if (auto *MD = dyn_cast<ObjCMethodDecl>(this)) {
    if (auto *ID = MD->getClassInterface())
      Ctx = ID;
  } else if (auto *PD = dyn_cast<ObjCPropertyDecl>(this)) {
    if (auto *MD = PD->getGetterMethodDecl())
      if (auto *ID = MD->getClassInterface())
        Ctx = ID;
  } else if (auto *ID = dyn_cast<ObjCIvarDecl>(this)) {
    if (auto *CI = ID->getContainingInterface())
      Ctx = CI;
  }

  if (Ctx->isFunctionOrMethod())
    return;

  using ContextsTy = SmallVector<const DeclContext *, 8>;
  ContextsTy Contexts;

  // Collect named contexts.
  while (Ctx) {
    if (isa<NamedDecl>(Ctx))
      Contexts.push_back(Ctx);
    Ctx = Ctx->getParent();
  }

  for (const DeclContext *DC : llvm::reverse(Contexts)) {
    if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
      OS << Spec->getName();
      const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
      printTemplateArgumentList(OS, TemplateArgs.asArray(), P);
    } else if (const auto *ND = dyn_cast<NamespaceDecl>(DC)) {
      if (P.SuppressUnwrittenScope &&
          (ND->isAnonymousNamespace() || ND->isInline()))
        continue;
      if (ND->isAnonymousNamespace()) {
        OS << (P.MSVCFormatting ? "`anonymous namespace\'"
                                : "(anonymous namespace)");
      }
      else
        OS << *ND;
    } else if (const auto *RD = dyn_cast<RecordDecl>(DC)) {
      if (!RD->getIdentifier())
        OS << "(anonymous " << RD->getKindName() << ')';
      else
        OS << *RD;
    } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
      const FunctionProtoType *FT = nullptr;
      if (FD->hasWrittenPrototype())
        FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>());

      OS << *FD << '(';
      if (FT) {
        unsigned NumParams = FD->getNumParams();
        for (unsigned i = 0; i < NumParams; ++i) {
          if (i)
            OS << ", ";
          OS << FD->getParamDecl(i)->getType().stream(P);
        }

        if (FT->isVariadic()) {
          if (NumParams > 0)
            OS << ", ";
          OS << "...";
        }
      }
      OS << ')';
    } else if (const auto *ED = dyn_cast<EnumDecl>(DC)) {
      // C++ [dcl.enum]p10: Each enum-name and each unscoped
      // enumerator is declared in the scope that immediately contains
      // the enum-specifier. Each scoped enumerator is declared in the
      // scope of the enumeration.
      // For the case of unscoped enumerator, do not include in the qualified
      // name any information about its enum enclosing scope, as its visibility
      // is global.
      if (ED->isScoped())
        OS << *ED;
      else
        continue;
    } else {
      OS << *cast<NamedDecl>(DC);
    }
    OS << "::";
  }
}

void NamedDecl::getNameForDiagnostic(raw_ostream &OS,
                                     const PrintingPolicy &Policy,
                                     bool Qualified) const {
  if (Qualified)
    printQualifiedName(OS, Policy);
  else
    printName(OS);
}

template<typename T> static bool isRedeclarableImpl(Redeclarable<T> *) {
  return true;
}
static bool isRedeclarableImpl(...) { return false; }
static bool isRedeclarable(Decl::Kind K) {
  switch (K) {
#define DECL(Type, Base) \
  case Decl::Type: \
    return isRedeclarableImpl((Type##Decl *)nullptr);
#define ABSTRACT_DECL(DECL)
#include "clang/AST/DeclNodes.inc"
  }
  llvm_unreachable("unknown decl kind");
}

bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
  assert(getDeclName() == OldD->getDeclName() && "Declaration name mismatch");

  // Never replace one imported declaration with another; we need both results
  // when re-exporting.
  if (OldD->isFromASTFile() && isFromASTFile())
    return false;

  // A kind mismatch implies that the declaration is not replaced.
  if (OldD->getKind() != getKind())
    return false;

  // For method declarations, we never replace. (Why?)
  if (isa<ObjCMethodDecl>(this))
    return false;

  // For parameters, pick the newer one. This is either an error or (in
  // Objective-C) permitted as an extension.
  if (isa<ParmVarDecl>(this))
    return true;

  // Inline namespaces can give us two declarations with the same
  // name and kind in the same scope but different contexts; we should
  // keep both declarations in this case.
  if (!this->getDeclContext()->getRedeclContext()->Equals(
          OldD->getDeclContext()->getRedeclContext()))
    return false;

  // Using declarations can be replaced if they import the same name from the
  // same context.
  if (auto *UD = dyn_cast<UsingDecl>(this)) {
    ASTContext &Context = getASTContext();
    return Context.getCanonicalNestedNameSpecifier(UD->getQualifier()) ==
           Context.getCanonicalNestedNameSpecifier(
               cast<UsingDecl>(OldD)->getQualifier());
  }
  if (auto *UUVD = dyn_cast<UnresolvedUsingValueDecl>(this)) {
    ASTContext &Context = getASTContext();
    return Context.getCanonicalNestedNameSpecifier(UUVD->getQualifier()) ==
           Context.getCanonicalNestedNameSpecifier(
                        cast<UnresolvedUsingValueDecl>(OldD)->getQualifier());
  }

  if (isRedeclarable(getKind())) {
    if (getCanonicalDecl() != OldD->getCanonicalDecl())
      return false;

    if (IsKnownNewer)
      return true;

    // Check whether this is actually newer than OldD. We want to keep the
    // newer declaration. This loop will usually only iterate once, because
    // OldD is usually the previous declaration.
    for (auto D : redecls()) {
      if (D == OldD)
        break;

      // If we reach the canonical declaration, then OldD is not actually older
      // than this one.
      //
      // FIXME: In this case, we should not add this decl to the lookup table.
      if (D->isCanonicalDecl())
        return false;
    }

    // It's a newer declaration of the same kind of declaration in the same
    // scope: we want this decl instead of the existing one.
    return true;
  }

  // In all other cases, we need to keep both declarations in case they have
  // different visibility. Any attempt to use the name will result in an
  // ambiguity if more than one is visible.
  return false;
}

bool NamedDecl::hasLinkage() const {
  return getFormalLinkage() != NoLinkage;
}

NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
  NamedDecl *ND = this;
  while (auto *UD = dyn_cast<UsingShadowDecl>(ND))
    ND = UD->getTargetDecl();

  if (auto *AD = dyn_cast<ObjCCompatibleAliasDecl>(ND))
    return AD->getClassInterface();

  if (auto *AD = dyn_cast<NamespaceAliasDecl>(ND))
    return AD->getNamespace();

  return ND;
}

bool NamedDecl::isCXXInstanceMember() const {
  if (!isCXXClassMember())
    return false;

  const NamedDecl *D = this;
  if (isa<UsingShadowDecl>(D))
    D = cast<UsingShadowDecl>(D)->getTargetDecl();

  if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
    return true;
  if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()))
    return MD->isInstance();
  return false;
}

//===----------------------------------------------------------------------===//
// DeclaratorDecl Implementation
//===----------------------------------------------------------------------===//

template <typename DeclT>
static SourceLocation getTemplateOrInnerLocStart(const DeclT *decl) {
  if (decl->getNumTemplateParameterLists() > 0)
    return decl->getTemplateParameterList(0)->getTemplateLoc();
  else
    return decl->getInnerLocStart();
}

SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const {
  TypeSourceInfo *TSI = getTypeSourceInfo();
  if (TSI) return TSI->getTypeLoc().getBeginLoc();
  return SourceLocation();
}

SourceLocation DeclaratorDecl::getTypeSpecEndLoc() const {
  TypeSourceInfo *TSI = getTypeSourceInfo();
  if (TSI) return TSI->getTypeLoc().getEndLoc();
  return SourceLocation();
}

void DeclaratorDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
  if (QualifierLoc) {
    // Make sure the extended decl info is allocated.
    if (!hasExtInfo()) {
      // Save (non-extended) type source info pointer.
      auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
      // Allocate external info struct.
      DeclInfo = new (getASTContext()) ExtInfo;
      // Restore savedTInfo into (extended) decl info.
      getExtInfo()->TInfo = savedTInfo;
    }
    // Set qualifier info.
    getExtInfo()->QualifierLoc = QualifierLoc;
  } else if (hasExtInfo()) {
    // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
    getExtInfo()->QualifierLoc = QualifierLoc;
  }
}

void DeclaratorDecl::setTrailingRequiresClause(Expr *TrailingRequiresClause) {
  assert(TrailingRequiresClause);
  // Make sure the extended decl info is allocated.
  if (!hasExtInfo()) {
    // Save (non-extended) type source info pointer.
    auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
    // Allocate external info struct.
    DeclInfo = new (getASTContext()) ExtInfo;
    // Restore savedTInfo into (extended) decl info.
    getExtInfo()->TInfo = savedTInfo;
  }
  // Set requires clause info.
  getExtInfo()->TrailingRequiresClause = TrailingRequiresClause;
}

void DeclaratorDecl::setTemplateParameterListsInfo(
    ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
  assert(!TPLists.empty());
  // Make sure the extended decl info is allocated.
  if (!hasExtInfo()) {
    // Save (non-extended) type source info pointer.
    auto *savedTInfo = DeclInfo.get<TypeSourceInfo*>();
    // Allocate external info struct.
    DeclInfo = new (getASTContext()) ExtInfo;
    // Restore savedTInfo into (extended) decl info.
    getExtInfo()->TInfo = savedTInfo;
  }
  // Set the template parameter lists info.
  getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
}

SourceLocation DeclaratorDecl::getOuterLocStart() const {
  return getTemplateOrInnerLocStart(this);
}

// Helper function: returns true if QT is or contains a type
// having a postfix component.
static bool typeIsPostfix(QualType QT) {
  while (true) {
    const Type* T = QT.getTypePtr();
    switch (T->getTypeClass()) {
    default:
      return false;
    case Type::Pointer:
      QT = cast<PointerType>(T)->getPointeeType();
      break;
    case Type::BlockPointer:
      QT = cast<BlockPointerType>(T)->getPointeeType();
      break;
    case Type::MemberPointer:
      QT = cast<MemberPointerType>(T)->getPointeeType();
      break;
    case Type::LValueReference:
    case Type::RValueReference:
      QT = cast<ReferenceType>(T)->getPointeeType();
      break;
    case Type::PackExpansion:
      QT = cast<PackExpansionType>(T)->getPattern();
      break;
    case Type::Paren:
    case Type::ConstantArray:
    case Type::DependentSizedArray:
    case Type::IncompleteArray:
    case Type::VariableArray:
    case Type::FunctionProto:
    case Type::FunctionNoProto:
      return true;
    }
  }
}

SourceRange DeclaratorDecl::getSourceRange() const {
  SourceLocation RangeEnd = getLocation();
  if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
    // If the declaration has no name or the type extends past the name take the
    // end location of the type.
    if (!getDeclName() || typeIsPostfix(TInfo->getType()))
      RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
  }
  return SourceRange(getOuterLocStart(), RangeEnd);
}

void QualifierInfo::setTemplateParameterListsInfo(
    ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
  // Free previous template parameters (if any).
  if (NumTemplParamLists > 0) {
    Context.Deallocate(TemplParamLists);
    TemplParamLists = nullptr;
    NumTemplParamLists = 0;
  }
  // Set info on matched template parameter lists (if any).
  if (!TPLists.empty()) {
    TemplParamLists = new (Context) TemplateParameterList *[TPLists.size()];
    NumTemplParamLists = TPLists.size();
    std::copy(TPLists.begin(), TPLists.end(), TemplParamLists);
  }
}

//===----------------------------------------------------------------------===//
// VarDecl Implementation
//===----------------------------------------------------------------------===//

const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
  switch (SC) {
  case SC_None:                 break;
  case SC_Auto:                 return "auto";
  case SC_Extern:               return "extern";
  case SC_PrivateExtern:        return "__private_extern__";
  case SC_Register:             return "register";
  case SC_Static:               return "static";
  }

  llvm_unreachable("Invalid storage class");
}

VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC,
                 SourceLocation StartLoc, SourceLocation IdLoc,
                 IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
                 StorageClass SC)
    : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
      redeclarable_base(C) {
  static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned),
                "VarDeclBitfields too large!");
  static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned),
                "ParmVarDeclBitfields too large!");
  static_assert(sizeof(NonParmVarDeclBitfields) <= sizeof(unsigned),
                "NonParmVarDeclBitfields too large!");
  AllBits = 0;
  VarDeclBits.SClass = SC;
  // Everything else is implicitly initialized to false.
}

VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC,
                         SourceLocation StartL, SourceLocation IdL,
                         IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
                         StorageClass S) {
  return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S);
}

VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID)
      VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
              QualType(), nullptr, SC_None);
}

void VarDecl::setStorageClass(StorageClass SC) {
  assert(isLegalForVariable(SC));
  VarDeclBits.SClass = SC;
}

VarDecl::TLSKind VarDecl::getTLSKind() const {
  switch (VarDeclBits.TSCSpec) {
  case TSCS_unspecified:
    if (!hasAttr<ThreadAttr>() &&
        !(getASTContext().getLangOpts().OpenMPUseTLS &&
          getASTContext().getTargetInfo().isTLSSupported() &&
          hasAttr<OMPThreadPrivateDeclAttr>()))
      return TLS_None;
    return ((getASTContext().getLangOpts().isCompatibleWithMSVC(
                LangOptions::MSVC2015)) ||
            hasAttr<OMPThreadPrivateDeclAttr>())
               ? TLS_Dynamic
               : TLS_Static;
  case TSCS___thread: // Fall through.
  case TSCS__Thread_local:
    return TLS_Static;
  case TSCS_thread_local:
    return TLS_Dynamic;
  }
  llvm_unreachable("Unknown thread storage class specifier!");
}

SourceRange VarDecl::getSourceRange() const {
  if (const Expr *Init = getInit()) {
    SourceLocation InitEnd = Init->getEndLoc();
    // If Init is implicit, ignore its source range and fallback on
    // DeclaratorDecl::getSourceRange() to handle postfix elements.
    if (InitEnd.isValid() && InitEnd != getLocation())
      return SourceRange(getOuterLocStart(), InitEnd);
  }
  return DeclaratorDecl::getSourceRange();
}

template<typename T>
static LanguageLinkage getDeclLanguageLinkage(const T &D) {
  // C++ [dcl.link]p1: All function types, function names with external linkage,
  // and variable names with external linkage have a language linkage.
  if (!D.hasExternalFormalLinkage())
    return NoLanguageLinkage;

  // Language linkage is a C++ concept, but saying that everything else in C has
  // C language linkage fits the implementation nicely.
  ASTContext &Context = D.getASTContext();
  if (!Context.getLangOpts().CPlusPlus)
    return CLanguageLinkage;

  // C++ [dcl.link]p4: A C language linkage is ignored in determining the
  // language linkage of the names of class members and the function type of
  // class member functions.
  const DeclContext *DC = D.getDeclContext();
  if (DC->isRecord())
    return CXXLanguageLinkage;

  // If the first decl is in an extern "C" context, any other redeclaration
  // will have C language linkage. If the first one is not in an extern "C"
  // context, we would have reported an error for any other decl being in one.
  if (isFirstInExternCContext(&D))
    return CLanguageLinkage;
  return CXXLanguageLinkage;
}

template<typename T>
static bool isDeclExternC(const T &D) {
  // Since the context is ignored for class members, they can only have C++
  // language linkage or no language linkage.
  const DeclContext *DC = D.getDeclContext();
  if (DC->isRecord()) {
    assert(D.getASTContext().getLangOpts().CPlusPlus);
    return false;
  }

  return D.getLanguageLinkage() == CLanguageLinkage;
}

LanguageLinkage VarDecl::getLanguageLinkage() const {
  return getDeclLanguageLinkage(*this);
}

bool VarDecl::isExternC() const {
  return isDeclExternC(*this);
}

bool VarDecl::isInExternCContext() const {
  return getLexicalDeclContext()->isExternCContext();
}

bool VarDecl::isInExternCXXContext() const {
  return getLexicalDeclContext()->isExternCXXContext();
}

VarDecl *VarDecl::getCanonicalDecl() { return getFirstDecl(); }

VarDecl::DefinitionKind
VarDecl::isThisDeclarationADefinition(ASTContext &C) const {
  if (isThisDeclarationADemotedDefinition())
    return DeclarationOnly;

  // C++ [basic.def]p2:
  //   A declaration is a definition unless [...] it contains the 'extern'
  //   specifier or a linkage-specification and neither an initializer [...],
  //   it declares a non-inline static data member in a class declaration [...],
  //   it declares a static data member outside a class definition and the variable
  //   was defined within the class with the constexpr specifier [...],
  // C++1y [temp.expl.spec]p15:
  //   An explicit specialization of a static data member or an explicit
  //   specialization of a static data member template is a definition if the
  //   declaration includes an initializer; otherwise, it is a declaration.
  //
  // FIXME: How do you declare (but not define) a partial specialization of
  // a static data member template outside the containing class?
  if (isStaticDataMember()) {
    if (isOutOfLine() &&
        !(getCanonicalDecl()->isInline() &&
          getCanonicalDecl()->isConstexpr()) &&
        (hasInit() ||
         // If the first declaration is out-of-line, this may be an
         // instantiation of an out-of-line partial specialization of a variable
         // template for which we have not yet instantiated the initializer.
         (getFirstDecl()->isOutOfLine()
              ? getTemplateSpecializationKind() == TSK_Undeclared
              : getTemplateSpecializationKind() !=
                    TSK_ExplicitSpecialization) ||
         isa<VarTemplatePartialSpecializationDecl>(this)))
      return Definition;
    else if (!isOutOfLine() && isInline())
      return Definition;
    else
      return DeclarationOnly;
  }
  // C99 6.7p5:
  //   A definition of an identifier is a declaration for that identifier that
  //   [...] causes storage to be reserved for that object.
  // Note: that applies for all non-file-scope objects.
  // C99 6.9.2p1:
  //   If the declaration of an identifier for an object has file scope and an
  //   initializer, the declaration is an external definition for the identifier
  if (hasInit())
    return Definition;

  if (hasDefiningAttr())
    return Definition;

  if (const auto *SAA = getAttr<SelectAnyAttr>())
    if (!SAA->isInherited())
      return Definition;

  // A variable template specialization (other than a static data member
  // template or an explicit specialization) is a declaration until we
  // instantiate its initializer.
  if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(this)) {
    if (VTSD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization &&
        !isa<VarTemplatePartialSpecializationDecl>(VTSD) &&
        !VTSD->IsCompleteDefinition)
      return DeclarationOnly;
  }

  if (hasExternalStorage())
    return DeclarationOnly;

  // [dcl.link] p7:
  //   A declaration directly contained in a linkage-specification is treated
  //   as if it contains the extern specifier for the purpose of determining
  //   the linkage of the declared name and whether it is a definition.
  if (isSingleLineLanguageLinkage(*this))
    return DeclarationOnly;

  // C99 6.9.2p2:
  //   A declaration of an object that has file scope without an initializer,
  //   and without a storage class specifier or the scs 'static', constitutes
  //   a tentative definition.
  // No such thing in C++.
  if (!C.getLangOpts().CPlusPlus && isFileVarDecl())
    return TentativeDefinition;

  // What's left is (in C, block-scope) declarations without initializers or
  // external storage. These are definitions.
  return Definition;
}

VarDecl *VarDecl::getActingDefinition() {
  DefinitionKind Kind = isThisDeclarationADefinition();
  if (Kind != TentativeDefinition)
    return nullptr;

  VarDecl *LastTentative = nullptr;
  VarDecl *First = getFirstDecl();
  for (auto I : First->redecls()) {
    Kind = I->isThisDeclarationADefinition();
    if (Kind == Definition)
      return nullptr;
    else if (Kind == TentativeDefinition)
      LastTentative = I;
  }
  return LastTentative;
}

VarDecl *VarDecl::getDefinition(ASTContext &C) {
  VarDecl *First = getFirstDecl();
  for (auto I : First->redecls()) {
    if (I->isThisDeclarationADefinition(C) == Definition)
      return I;
  }
  return nullptr;
}

VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const {
  DefinitionKind Kind = DeclarationOnly;

  const VarDecl *First = getFirstDecl();
  for (auto I : First->redecls()) {
    Kind = std::max(Kind, I->isThisDeclarationADefinition(C));
    if (Kind == Definition)
      break;
  }

  return Kind;
}

const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const {
  for (auto I : redecls()) {
    if (auto Expr = I->getInit()) {
      D = I;
      return Expr;
    }
  }
  return nullptr;
}

bool VarDecl::hasInit() const {
  if (auto *P = dyn_cast<ParmVarDecl>(this))
    if (P->hasUnparsedDefaultArg() || P->hasUninstantiatedDefaultArg())
      return false;

  return !Init.isNull();
}

Expr *VarDecl::getInit() {
  if (!hasInit())
    return nullptr;

  if (auto *S = Init.dyn_cast<Stmt *>())
    return cast<Expr>(S);

  return cast_or_null<Expr>(Init.get<EvaluatedStmt *>()->Value);
}

Stmt **VarDecl::getInitAddress() {
  if (auto *ES = Init.dyn_cast<EvaluatedStmt *>())
    return &ES->Value;

  return Init.getAddrOfPtr1();
}

VarDecl *VarDecl::getInitializingDeclaration() {
  VarDecl *Def = nullptr;
  for (auto I : redecls()) {
    if (I->hasInit())
      return I;

    if (I->isThisDeclarationADefinition()) {
      if (isStaticDataMember())
        return I;
      else
        Def = I;
    }
  }
  return Def;
}

bool VarDecl::isOutOfLine() const {
  if (Decl::isOutOfLine())
    return true;

  if (!isStaticDataMember())
    return false;

  // If this static data member was instantiated from a static data member of
  // a class template, check whether that static data member was defined
  // out-of-line.
  if (VarDecl *VD = getInstantiatedFromStaticDataMember())
    return VD->isOutOfLine();

  return false;
}

void VarDecl::setInit(Expr *I) {
  if (auto *Eval = Init.dyn_cast<EvaluatedStmt *>()) {
    Eval->~EvaluatedStmt();
    getASTContext().Deallocate(Eval);
  }

  Init = I;
}

bool VarDecl::mightBeUsableInConstantExpressions(ASTContext &C) const {
  const LangOptions &Lang = C.getLangOpts();

  if (!Lang.CPlusPlus)
    return false;

  // Function parameters are never usable in constant expressions.
  if (isa<ParmVarDecl>(this))
    return false;

  // In C++11, any variable of reference type can be used in a constant
  // expression if it is initialized by a constant expression.
  if (Lang.CPlusPlus11 && getType()->isReferenceType())
    return true;

  // Only const objects can be used in constant expressions in C++. C++98 does
  // not require the variable to be non-volatile, but we consider this to be a
  // defect.
  if (!getType().isConstQualified() || getType().isVolatileQualified())
    return false;

  // In C++, const, non-volatile variables of integral or enumeration types
  // can be used in constant expressions.
  if (getType()->isIntegralOrEnumerationType())
    return true;

  // Additionally, in C++11, non-volatile constexpr variables can be used in
  // constant expressions.
  return Lang.CPlusPlus11 && isConstexpr();
}

bool VarDecl::isUsableInConstantExpressions(ASTContext &Context) const {
  // C++2a [expr.const]p3:
  //   A variable is usable in constant expressions after its initializing
  //   declaration is encountered...
  const VarDecl *DefVD = nullptr;
  const Expr *Init = getAnyInitializer(DefVD);
  if (!Init || Init->isValueDependent() || getType()->isDependentType())
    return false;
  //   ... if it is a constexpr variable, or it is of reference type or of
  //   const-qualified integral or enumeration type, ...
  if (!DefVD->mightBeUsableInConstantExpressions(Context))
    return false;
  //   ... and its initializer is a constant initializer.
  return DefVD->checkInitIsICE();
}

/// Convert the initializer for this declaration to the elaborated EvaluatedStmt
/// form, which contains extra information on the evaluated value of the
/// initializer.
EvaluatedStmt *VarDecl::ensureEvaluatedStmt() const {
  auto *Eval = Init.dyn_cast<EvaluatedStmt *>();
  if (!Eval) {
    // Note: EvaluatedStmt contains an APValue, which usually holds
    // resources not allocated from the ASTContext.  We need to do some
    // work to avoid leaking those, but we do so in VarDecl::evaluateValue
    // where we can detect whether there's anything to clean up or not.
    Eval = new (getASTContext()) EvaluatedStmt;
    Eval->Value = Init.get<Stmt *>();
    Init = Eval;
  }
  return Eval;
}

APValue *VarDecl::evaluateValue() const {
  SmallVector<PartialDiagnosticAt, 8> Notes;
  return evaluateValue(Notes);
}

APValue *VarDecl::evaluateValue(
    SmallVectorImpl<PartialDiagnosticAt> &Notes) const {
  EvaluatedStmt *Eval = ensureEvaluatedStmt();

  // We only produce notes indicating why an initializer is non-constant the
  // first time it is evaluated. FIXME: The notes won't always be emitted the
  // first time we try evaluation, so might not be produced at all.
  if (Eval->WasEvaluated)
    return Eval->Evaluated.isAbsent() ? nullptr : &Eval->Evaluated;

  const auto *Init = cast<Expr>(Eval->Value);
  assert(!Init->isValueDependent());

  if (Eval->IsEvaluating) {
    // FIXME: Produce a diagnostic for self-initialization.
    Eval->CheckedICE = true;
    Eval->IsICE = false;
    return nullptr;
  }

  Eval->IsEvaluating = true;

  bool Result = Init->EvaluateAsInitializer(Eval->Evaluated, getASTContext(),
                                            this, Notes);

  // Ensure the computed APValue is cleaned up later if evaluation succeeded,
  // or that it's empty (so that there's nothing to clean up) if evaluation
  // failed.
  if (!Result)
    Eval->Evaluated = APValue();
  else if (Eval->Evaluated.needsCleanup())
    getASTContext().addDestruction(&Eval->Evaluated);

  Eval->IsEvaluating = false;
  Eval->WasEvaluated = true;

  // In C++11, we have determined whether the initializer was a constant
  // expression as a side-effect.
  if (getASTContext().getLangOpts().CPlusPlus11 && !Eval->CheckedICE) {
    Eval->CheckedICE = true;
    Eval->IsICE = Result && Notes.empty();
  }

  return Result ? &Eval->Evaluated : nullptr;
}

APValue *VarDecl::getEvaluatedValue() const {
  if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
    if (Eval->WasEvaluated)
      return &Eval->Evaluated;

  return nullptr;
}

bool VarDecl::isInitKnownICE() const {
  if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
    return Eval->CheckedICE;

  return false;
}

bool VarDecl::isInitICE() const {
  assert(isInitKnownICE() &&
         "Check whether we already know that the initializer is an ICE");
  return Init.get<EvaluatedStmt *>()->IsICE;
}

bool VarDecl::checkInitIsICE() const {
  // Initializers of weak variables are never ICEs.
  if (isWeak())
    return false;

  EvaluatedStmt *Eval = ensureEvaluatedStmt();
  if (Eval->CheckedICE)
    // We have already checked whether this subexpression is an
    // integral constant expression.
    return Eval->IsICE;

  const auto *Init = cast<Expr>(Eval->Value);
  assert(!Init->isValueDependent());

  // In C++11, evaluate the initializer to check whether it's a constant
  // expression.
  if (getASTContext().getLangOpts().CPlusPlus11) {
    SmallVector<PartialDiagnosticAt, 8> Notes;
    evaluateValue(Notes);
    return Eval->IsICE;
  }

  // It's an ICE whether or not the definition we found is
  // out-of-line.  See DR 721 and the discussion in Clang PR
  // 6206 for details.

  if (Eval->CheckingICE)
    return false;
  Eval->CheckingICE = true;

  Eval->IsICE = Init->isIntegerConstantExpr(getASTContext());
  Eval->CheckingICE = false;
  Eval->CheckedICE = true;
  return Eval->IsICE;
}

bool VarDecl::isParameterPack() const {
  return isa<PackExpansionType>(getType());
}

template<typename DeclT>
static DeclT *getDefinitionOrSelf(DeclT *D) {
  assert(D);
  if (auto *Def = D->getDefinition())
    return Def;
  return D;
}

bool VarDecl::isEscapingByref() const {
  return hasAttr<BlocksAttr>() && NonParmVarDeclBits.EscapingByref;
}

bool VarDecl::isNonEscapingByref() const {
  return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref;
}

VarDecl *VarDecl::getTemplateInstantiationPattern() const {
  const VarDecl *VD = this;

  // If this is an instantiated member, walk back to the template from which
  // it was instantiated.
  if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) {
    if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
      VD = VD->getInstantiatedFromStaticDataMember();
      while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
        VD = NewVD;
    }
  }

  // If it's an instantiated variable template specialization, find the
  // template or partial specialization from which it was instantiated.
  if (auto *VDTemplSpec = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
    if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
      auto From = VDTemplSpec->getInstantiatedFrom();
      if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
        while (!VTD->isMemberSpecialization()) {
          auto *NewVTD = VTD->getInstantiatedFromMemberTemplate();
          if (!NewVTD)
            break;
          VTD = NewVTD;
        }
        return getDefinitionOrSelf(VTD->getTemplatedDecl());
      }
      if (auto *VTPSD =
              From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
        while (!VTPSD->isMemberSpecialization()) {
          auto *NewVTPSD = VTPSD->getInstantiatedFromMember();
          if (!NewVTPSD)
            break;
          VTPSD = NewVTPSD;
        }
        return getDefinitionOrSelf<VarDecl>(VTPSD);
      }
    }
  }

  // If this is the pattern of a variable template, find where it was
  // instantiated from. FIXME: Is this necessary?
  if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
    while (!VarTemplate->isMemberSpecialization()) {
      auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
      if (!NewVT)
        break;
      VarTemplate = NewVT;
    }

    return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
  }

  if (VD == this)
    return nullptr;
  return getDefinitionOrSelf(const_cast<VarDecl*>(VD));
}

VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const {
  if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
    return cast<VarDecl>(MSI->getInstantiatedFrom());

  return nullptr;
}

TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
  if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
    return Spec->getSpecializationKind();

  if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
    return MSI->getTemplateSpecializationKind();

  return TSK_Undeclared;
}

TemplateSpecializationKind
VarDecl::getTemplateSpecializationKindForInstantiation() const {
  if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
    return MSI->getTemplateSpecializationKind();

  if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
    return Spec->getSpecializationKind();

  return TSK_Undeclared;
}

SourceLocation VarDecl::getPointOfInstantiation() const {
  if (const auto *Spec = dyn_cast<VarTemplateSpecializationDecl>(this))
    return Spec->getPointOfInstantiation();

  if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
    return MSI->getPointOfInstantiation();

  return SourceLocation();
}

VarTemplateDecl *VarDecl::getDescribedVarTemplate() const {
  return getASTContext().getTemplateOrSpecializationInfo(this)
      .dyn_cast<VarTemplateDecl *>();
}

void VarDecl::setDescribedVarTemplate(VarTemplateDecl *Template) {
  getASTContext().setTemplateOrSpecializationInfo(this, Template);
}

bool VarDecl::isKnownToBeDefined() const {
  const auto &LangOpts = getASTContext().getLangOpts();
  // In CUDA mode without relocatable device code, variables of form 'extern
  // __shared__ Foo foo[]' are pointers to the base of the GPU core's shared
  // memory pool.  These are never undefined variables, even if they appear
  // inside of an anon namespace or static function.
  //
  // With CUDA relocatable device code enabled, these variables don't get
  // special handling; they're treated like regular extern variables.
  if (LangOpts.CUDA && !LangOpts.GPURelocatableDeviceCode &&
      hasExternalStorage() && hasAttr<CUDASharedAttr>() &&
      isa<IncompleteArrayType>(getType()))
    return true;

  return hasDefinition();
}

bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
  return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() ||
                                (!Ctx.getLangOpts().RegisterStaticDestructors &&
                                 !hasAttr<AlwaysDestroyAttr>()));
}

QualType::DestructionKind
VarDecl::needsDestruction(const ASTContext &Ctx) const {
  if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>())
    if (Eval->HasConstantDestruction)
      return QualType::DK_none;

  if (isNoDestroy(Ctx))
    return QualType::DK_none;

  return getType().isDestructedType();
}

MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {
  if (isStaticDataMember())
    // FIXME: Remove ?
    // return getASTContext().getInstantiatedFromStaticDataMember(this);
    return getASTContext().getTemplateOrSpecializationInfo(this)
        .dyn_cast<MemberSpecializationInfo *>();
  return nullptr;
}

void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
                                         SourceLocation PointOfInstantiation) {
  assert((isa<VarTemplateSpecializationDecl>(this) ||
          getMemberSpecializationInfo()) &&
         "not a variable or static data member template specialization");

  if (VarTemplateSpecializationDecl *Spec =
          dyn_cast<VarTemplateSpecializationDecl>(this)) {
    Spec->setSpecializationKind(TSK);
    if (TSK != TSK_ExplicitSpecialization &&
        PointOfInstantiation.isValid() &&
        Spec->getPointOfInstantiation().isInvalid()) {
      Spec->setPointOfInstantiation(PointOfInstantiation);
      if (ASTMutationListener *L = getASTContext().getASTMutationListener())
        L->InstantiationRequested(this);
    }
  } else if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {
    MSI->setTemplateSpecializationKind(TSK);
    if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&
        MSI->getPointOfInstantiation().isInvalid()) {
      MSI->setPointOfInstantiation(PointOfInstantiation);
      if (ASTMutationListener *L = getASTContext().getASTMutationListener())
        L->InstantiationRequested(this);
    }
  }
}

void
VarDecl::setInstantiationOfStaticDataMember(VarDecl *VD,
                                            TemplateSpecializationKind TSK) {
  assert(getASTContext().getTemplateOrSpecializationInfo(this).isNull() &&
         "Previous template or instantiation?");
  getASTContext().setInstantiatedFromStaticDataMember(this, VD, TSK);
}

//===----------------------------------------------------------------------===//
// ParmVarDecl Implementation
//===----------------------------------------------------------------------===//

ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC,
                                 SourceLocation StartLoc,
                                 SourceLocation IdLoc, IdentifierInfo *Id,
                                 QualType T, TypeSourceInfo *TInfo,
                                 StorageClass S, Expr *DefArg) {
  return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo,
                                 S, DefArg);
}

QualType ParmVarDecl::getOriginalType() const {
  TypeSourceInfo *TSI = getTypeSourceInfo();
  QualType T = TSI ? TSI->getType() : getType();
  if (const auto *DT = dyn_cast<DecayedType>(T))
    return DT->getOriginalType();
  return T;
}

ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID)
      ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(),
                  nullptr, QualType(), nullptr, SC_None, nullptr);
}

SourceRange ParmVarDecl::getSourceRange() const {
  if (!hasInheritedDefaultArg()) {
    SourceRange ArgRange = getDefaultArgRange();
    if (ArgRange.isValid())
      return SourceRange(getOuterLocStart(), ArgRange.getEnd());
  }

  // DeclaratorDecl considers the range of postfix types as overlapping with the
  // declaration name, but this is not the case with parameters in ObjC methods.
  if (isa<ObjCMethodDecl>(getDeclContext()))
    return SourceRange(DeclaratorDecl::getBeginLoc(), getLocation());

  return DeclaratorDecl::getSourceRange();
}

Expr *ParmVarDecl::getDefaultArg() {
  assert(!hasUnparsedDefaultArg() && "Default argument is not yet parsed!");
  assert(!hasUninstantiatedDefaultArg() &&
         "Default argument is not yet instantiated!");

  Expr *Arg = getInit();
  if (auto *E = dyn_cast_or_null<FullExpr>(Arg))
    return E->getSubExpr();

  return Arg;
}

void ParmVarDecl::setDefaultArg(Expr *defarg) {
  ParmVarDeclBits.DefaultArgKind = DAK_Normal;
  Init = defarg;
}

SourceRange ParmVarDecl::getDefaultArgRange() const {
  switch (ParmVarDeclBits.DefaultArgKind) {
  case DAK_None:
  case DAK_Unparsed:
    // Nothing we can do here.
    return SourceRange();

  case DAK_Uninstantiated:
    return getUninstantiatedDefaultArg()->getSourceRange();

  case DAK_Normal:
    if (const Expr *E = getInit())
      return E->getSourceRange();

    // Missing an actual expression, may be invalid.
    return SourceRange();
  }
  llvm_unreachable("Invalid default argument kind.");
}

void ParmVarDecl::setUninstantiatedDefaultArg(Expr *arg) {
  ParmVarDeclBits.DefaultArgKind = DAK_Uninstantiated;
  Init = arg;
}

Expr *ParmVarDecl::getUninstantiatedDefaultArg() {
  assert(hasUninstantiatedDefaultArg() &&
         "Wrong kind of initialization expression!");
  return cast_or_null<Expr>(Init.get<Stmt *>());
}

bool ParmVarDecl::hasDefaultArg() const {
  // FIXME: We should just return false for DAK_None here once callers are
  // prepared for the case that we encountered an invalid default argument and
  // were unable to even build an invalid expression.
  return hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg() ||
         !Init.isNull();
}

void ParmVarDecl::setParameterIndexLarge(unsigned parameterIndex) {
  getASTContext().setParameterIndex(this, parameterIndex);
  ParmVarDeclBits.ParameterIndex = ParameterIndexSentinel;
}

unsigned ParmVarDecl::getParameterIndexLarge() const {
  return getASTContext().getParameterIndex(this);
}

//===----------------------------------------------------------------------===//
// FunctionDecl Implementation
//===----------------------------------------------------------------------===//

FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
                           SourceLocation StartLoc,
                           const DeclarationNameInfo &NameInfo, QualType T,
                           TypeSourceInfo *TInfo, StorageClass S,
                           bool isInlineSpecified,
                           ConstexprSpecKind ConstexprKind,
                           Expr *TrailingRequiresClause)
    : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo,
                     StartLoc),
      DeclContext(DK), redeclarable_base(C), Body(), ODRHash(0),
      EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {
  assert(T.isNull() || T->isFunctionType());
  FunctionDeclBits.SClass = S;
  FunctionDeclBits.IsInline = isInlineSpecified;
  FunctionDeclBits.IsInlineSpecified = isInlineSpecified;
  FunctionDeclBits.IsVirtualAsWritten = false;
  FunctionDeclBits.IsPure = false;
  FunctionDeclBits.HasInheritedPrototype = false;
  FunctionDeclBits.HasWrittenPrototype = true;
  FunctionDeclBits.IsDeleted = false;
  FunctionDeclBits.IsTrivial = false;
  FunctionDeclBits.IsTrivialForCall = false;
  FunctionDeclBits.IsDefaulted = false;
  FunctionDeclBits.IsExplicitlyDefaulted = false;
  FunctionDeclBits.HasDefaultedFunctionInfo = false;
  FunctionDeclBits.HasImplicitReturnZero = false;
  FunctionDeclBits.IsLateTemplateParsed = false;
  FunctionDeclBits.ConstexprKind = ConstexprKind;
  FunctionDeclBits.InstantiationIsPending = false;
  FunctionDeclBits.UsesSEHTry = false;
  FunctionDeclBits.UsesFPIntrin = false;
  FunctionDeclBits.HasSkippedBody = false;
  FunctionDeclBits.WillHaveBody = false;
  FunctionDeclBits.IsMultiVersion = false;
  FunctionDeclBits.IsCopyDeductionCandidate = false;
  FunctionDeclBits.HasODRHash = false;
  if (TrailingRequiresClause)
    setTrailingRequiresClause(TrailingRequiresClause);
}

void FunctionDecl::getNameForDiagnostic(
    raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
  NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
  const TemplateArgumentList *TemplateArgs = getTemplateSpecializationArgs();
  if (TemplateArgs)
    printTemplateArgumentList(OS, TemplateArgs->asArray(), Policy);
}

bool FunctionDecl::isVariadic() const {
  if (const auto *FT = getType()->getAs<FunctionProtoType>())
    return FT->isVariadic();
  return false;
}

FunctionDecl::DefaultedFunctionInfo *
FunctionDecl::DefaultedFunctionInfo::Create(ASTContext &Context,
                                            ArrayRef<DeclAccessPair> Lookups) {
  DefaultedFunctionInfo *Info = new (Context.Allocate(
      totalSizeToAlloc<DeclAccessPair>(Lookups.size()),
      std::max(alignof(DefaultedFunctionInfo), alignof(DeclAccessPair))))
      DefaultedFunctionInfo;
  Info->NumLookups = Lookups.size();
  std::uninitialized_copy(Lookups.begin(), Lookups.end(),
                          Info->getTrailingObjects<DeclAccessPair>());
  return Info;
}

void FunctionDecl::setDefaultedFunctionInfo(DefaultedFunctionInfo *Info) {
  assert(!FunctionDeclBits.HasDefaultedFunctionInfo && "already have this");
  assert(!Body && "can't replace function body with defaulted function info");

  FunctionDeclBits.HasDefaultedFunctionInfo = true;
  DefaultedInfo = Info;
}

FunctionDecl::DefaultedFunctionInfo *
FunctionDecl::getDefaultedFunctionInfo() const {
  return FunctionDeclBits.HasDefaultedFunctionInfo ? DefaultedInfo : nullptr;
}

bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
  for (auto I : redecls()) {
    if (I->doesThisDeclarationHaveABody()) {
      Definition = I;
      return true;
    }
  }

  return false;
}

bool FunctionDecl::hasTrivialBody() const {
  Stmt *S = getBody();
  if (!S) {
    // Since we don't have a body for this function, we don't know if it's
    // trivial or not.
    return false;
  }

  if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
    return true;
  return false;
}

bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const {
  for (auto I : redecls()) {
    if (I->isThisDeclarationADefinition()) {
      Definition = I;
      return true;
    }
  }

  return false;
}

Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
  if (!hasBody(Definition))
    return nullptr;

  assert(!Definition->FunctionDeclBits.HasDefaultedFunctionInfo &&
         "definition should not have a body");
  if (Definition->Body)
    return Definition->Body.get(getASTContext().getExternalSource());

  return nullptr;
}

void FunctionDecl::setBody(Stmt *B) {
  FunctionDeclBits.HasDefaultedFunctionInfo = false;
  Body = LazyDeclStmtPtr(B);
  if (B)
    EndRangeLoc = B->getEndLoc();
}

void FunctionDecl::setPure(bool P) {
  FunctionDeclBits.IsPure = P;
  if (P)
    if (auto *Parent = dyn_cast<CXXRecordDecl>(getDeclContext()))
      Parent->markedVirtualFunctionPure();
}

template<std::size_t Len>
static bool isNamed(const NamedDecl *ND, const char (&Str)[Len]) {
  IdentifierInfo *II = ND->getIdentifier();
  return II && II->isStr(Str);
}

bool FunctionDecl::isMain() const {
  const TranslationUnitDecl *tunit =
    dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
  return tunit &&
         !tunit->getASTContext().getLangOpts().Freestanding &&
         isNamed(this, "main");
}

bool FunctionDecl::isMSVCRTEntryPoint() const {
  const TranslationUnitDecl *TUnit =
      dyn_cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext());
  if (!TUnit)
    return false;

  // Even though we aren't really targeting MSVCRT if we are freestanding,
  // semantic analysis for these functions remains the same.

  // MSVCRT entry points only exist on MSVCRT targets.
  if (!TUnit->getASTContext().getTargetInfo().getTriple().isOSMSVCRT())
    return false;

  // Nameless functions like constructors cannot be entry points.
  if (!getIdentifier())
    return false;

  return llvm::StringSwitch<bool>(getName())
      .Cases("main",     // an ANSI console app
             "wmain",    // a Unicode console App
             "WinMain",  // an ANSI GUI app
             "wWinMain", // a Unicode GUI app
             "DllMain",  // a DLL
             true)
      .Default(false);
}

bool FunctionDecl::isReservedGlobalPlacementOperator() const {
  assert(getDeclName().getNameKind() == DeclarationName::CXXOperatorName);
  assert(getDeclName().getCXXOverloadedOperator() == OO_New ||
         getDeclName().getCXXOverloadedOperator() == OO_Delete ||
         getDeclName().getCXXOverloadedOperator() == OO_Array_New ||
         getDeclName().getCXXOverloadedOperator() == OO_Array_Delete);

  if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
    return false;

  const auto *proto = getType()->castAs<FunctionProtoType>();
  if (proto->getNumParams() != 2 || proto->isVariadic())
    return false;

  ASTContext &Context =
    cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext())
      ->getASTContext();

  // The result type and first argument type are constant across all
  // these operators.  The second argument must be exactly void*.
  return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy);
}

bool FunctionDecl::isReplaceableGlobalAllocationFunction(
    Optional<unsigned> *AlignmentParam, bool *IsNothrow) const {
  if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName)
    return false;
  if (getDeclName().getCXXOverloadedOperator() != OO_New &&
      getDeclName().getCXXOverloadedOperator() != OO_Delete &&
      getDeclName().getCXXOverloadedOperator() != OO_Array_New &&
      getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
    return false;

  if (isa<CXXRecordDecl>(getDeclContext()))
    return false;

  // This can only fail for an invalid 'operator new' declaration.
  if (!getDeclContext()->getRedeclContext()->isTranslationUnit())
    return false;

  const auto *FPT = getType()->castAs<FunctionProtoType>();
  if (FPT->getNumParams() == 0 || FPT->getNumParams() > 3 || FPT->isVariadic())
    return false;

  // If this is a single-parameter function, it must be a replaceable global
  // allocation or deallocation function.
  if (FPT->getNumParams() == 1)
    return true;

  unsigned Params = 1;
  QualType Ty = FPT->getParamType(Params);
  ASTContext &Ctx = getASTContext();

  auto Consume = [&] {
    ++Params;
    Ty = Params < FPT->getNumParams() ? FPT->getParamType(Params) : QualType();
  };

  // In C++14, the next parameter can be a 'std::size_t' for sized delete.
  bool IsSizedDelete = false;
  if (Ctx.getLangOpts().SizedDeallocation &&
      (getDeclName().getCXXOverloadedOperator() == OO_Delete ||
       getDeclName().getCXXOverloadedOperator() == OO_Array_Delete) &&
      Ctx.hasSameType(Ty, Ctx.getSizeType())) {
    IsSizedDelete = true;
    Consume();
  }

  // In C++17, the next parameter can be a 'std::align_val_t' for aligned
  // new/delete.
  if (Ctx.getLangOpts().AlignedAllocation && !Ty.isNull() && Ty->isAlignValT()) {
    Consume();
    if (AlignmentParam)
      *AlignmentParam = Params;
  }

  // Finally, if this is not a sized delete, the final parameter can
  // be a 'const std::nothrow_t&'.
  if (!IsSizedDelete && !Ty.isNull() && Ty->isReferenceType()) {
    Ty = Ty->getPointeeType();
    if (Ty.getCVRQualifiers() != Qualifiers::Const)
      return false;
    if (Ty->isNothrowT()) {
      if (IsNothrow)
        *IsNothrow = true;
      Consume();
    }
  }

  return Params == FPT->getNumParams();
}

bool FunctionDecl::isInlineBuiltinDeclaration() const {
  if (!getBuiltinID())
    return false;

  const FunctionDecl *Definition;
  return hasBody(Definition) && Definition->isInlineSpecified();
}

bool FunctionDecl::isDestroyingOperatorDelete() const {
  // C++ P0722:
  //   Within a class C, a single object deallocation function with signature
  //     (T, std::destroying_delete_t, <more params>)
  //   is a destroying operator delete.
  if (!isa<CXXMethodDecl>(this) || getOverloadedOperator() != OO_Delete ||
      getNumParams() < 2)
    return false;

  auto *RD = getParamDecl(1)->getType()->getAsCXXRecordDecl();
  return RD && RD->isInStdNamespace() && RD->getIdentifier() &&
         RD->getIdentifier()->isStr("destroying_delete_t");
}

LanguageLinkage FunctionDecl::getLanguageLinkage() const {
  return getDeclLanguageLinkage(*this);
}

bool FunctionDecl::isExternC() const {
  return isDeclExternC(*this);
}

bool FunctionDecl::isInExternCContext() const {
  if (hasAttr<OpenCLKernelAttr>())
    return true;
  return getLexicalDeclContext()->isExternCContext();
}

bool FunctionDecl::isInExternCXXContext() const {
  return getLexicalDeclContext()->isExternCXXContext();
}

bool FunctionDecl::isGlobal() const {
  if (const auto *Method = dyn_cast<CXXMethodDecl>(this))
    return Method->isStatic();

  if (getCanonicalDecl()->getStorageClass() == SC_Static)
    return false;

  for (const DeclContext *DC = getDeclContext();
       DC->isNamespace();
       DC = DC->getParent()) {
    if (const auto *Namespace = cast<NamespaceDecl>(DC)) {
      if (!Namespace->getDeclName())
        return false;
      break;
    }
  }

  return true;
}

bool FunctionDecl::isNoReturn() const {
  if (hasAttr<NoReturnAttr>() || hasAttr<CXX11NoReturnAttr>() ||
      hasAttr<C11NoReturnAttr>())
    return true;

  if (auto *FnTy = getType()->getAs<FunctionType>())
    return FnTy->getNoReturnAttr();

  return false;
}


MultiVersionKind FunctionDecl::getMultiVersionKind() const {
  if (hasAttr<TargetAttr>())
    return MultiVersionKind::Target;
  if (hasAttr<CPUDispatchAttr>())
    return MultiVersionKind::CPUDispatch;
  if (hasAttr<CPUSpecificAttr>())
    return MultiVersionKind::CPUSpecific;
  return MultiVersionKind::None;
}

bool FunctionDecl::isCPUDispatchMultiVersion() const {
  return isMultiVersion() && hasAttr<CPUDispatchAttr>();
}

bool FunctionDecl::isCPUSpecificMultiVersion() const {
  return isMultiVersion() && hasAttr<CPUSpecificAttr>();
}

bool FunctionDecl::isTargetMultiVersion() const {
  return isMultiVersion() && hasAttr<TargetAttr>();
}

void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
  redeclarable_base::setPreviousDecl(PrevDecl);

  if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
    FunctionTemplateDecl *PrevFunTmpl
      = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr;
    assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
    FunTmpl->setPreviousDecl(PrevFunTmpl);
  }

  if (PrevDecl && PrevDecl->isInlined())
    setImplicitlyInline(true);
}

FunctionDecl *FunctionDecl::getCanonicalDecl() { return getFirstDecl(); }

/// Returns a value indicating whether this function corresponds to a builtin
/// function.
///
/// The function corresponds to a built-in function if it is declared at
/// translation scope or within an extern "C" block and its name matches with
/// the name of a builtin. The returned value will be 0 for functions that do
/// not correspond to a builtin, a value of type \c Builtin::ID if in the
/// target-independent range \c [1,Builtin::First), or a target-specific builtin
/// value.
///
/// \param ConsiderWrapperFunctions If true, we should consider wrapper
/// functions as their wrapped builtins. This shouldn't be done in general, but
/// it's useful in Sema to diagnose calls to wrappers based on their semantics.
unsigned FunctionDecl::getBuiltinID(bool ConsiderWrapperFunctions) const {
  unsigned BuiltinID;

  if (const auto *ABAA = getAttr<ArmBuiltinAliasAttr>()) {
    BuiltinID = ABAA->getBuiltinName()->getBuiltinID();
  } else {
    if (!getIdentifier())
      return 0;

    BuiltinID = getIdentifier()->getBuiltinID();
  }

  if (!BuiltinID)
    return 0;

  ASTContext &Context = getASTContext();
  if (Context.getLangOpts().CPlusPlus) {
    const auto *LinkageDecl =
        dyn_cast<LinkageSpecDecl>(getFirstDecl()->getDeclContext());
    // In C++, the first declaration of a builtin is always inside an implicit
    // extern "C".
    // FIXME: A recognised library function may not be directly in an extern "C"
    // declaration, for instance "extern "C" { namespace std { decl } }".
    if (!LinkageDecl) {
      if (BuiltinID == Builtin::BI__GetExceptionInfo &&
          Context.getTargetInfo().getCXXABI().isMicrosoft())
        return Builtin::BI__GetExceptionInfo;
      return 0;
    }
    if (LinkageDecl->getLanguage() != LinkageSpecDecl::lang_c)
      return 0;
  }

  // If the function is marked "overloadable", it has a different mangled name
  // and is not the C library function.
  if (!ConsiderWrapperFunctions && hasAttr<OverloadableAttr>() &&
      !hasAttr<ArmBuiltinAliasAttr>())
    return 0;

  if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
    return BuiltinID;

  // This function has the name of a known C library
  // function. Determine whether it actually refers to the C library
  // function or whether it just has the same name.

  // If this is a static function, it's not a builtin.
  if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static)
    return 0;

  // OpenCL v1.2 s6.9.f - The library functions defined in
  // the C99 standard headers are not available.
  if (Context.getLangOpts().OpenCL &&
      Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID))
    return 0;

  // CUDA does not have device-side standard library. printf and malloc are the
  // only special cases that are supported by device-side runtime.
  if (Context.getLangOpts().CUDA && hasAttr<CUDADeviceAttr>() &&
      !hasAttr<CUDAHostAttr>() &&
      !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
    return 0;

  // As AMDGCN implementation of OpenMP does not have a device-side standard
  // library, none of the predefined library functions except printf and malloc
  // should be treated as a builtin i.e. 0 should be returned for them.
  if (Context.getTargetInfo().getTriple().isAMDGCN() &&
      Context.getLangOpts().OpenMPIsDevice &&
      Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
      !(BuiltinID == Builtin::BIprintf || BuiltinID == Builtin::BImalloc))
    return 0;

  return BuiltinID;
}

/// getNumParams - Return the number of parameters this function must have
/// based on its FunctionType.  This is the length of the ParamInfo array
/// after it has been created.
unsigned FunctionDecl::getNumParams() const {
  const auto *FPT = getType()->getAs<FunctionProtoType>();
  return FPT ? FPT->getNumParams() : 0;
}

void FunctionDecl::setParams(ASTContext &C,
                             ArrayRef<ParmVarDecl *> NewParamInfo) {
  assert(!ParamInfo && "Already has param info!");
  assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!");

  // Zero params -> null pointer.
  if (!NewParamInfo.empty()) {
    ParamInfo = new (C) ParmVarDecl*[NewParamInfo.size()];
    std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
  }
}

/// getMinRequiredArguments - Returns the minimum number of arguments
/// needed to call this function. This may be fewer than the number of
/// function parameters, if some of the parameters have default
/// arguments (in C++) or are parameter packs (C++11).
unsigned FunctionDecl::getMinRequiredArguments() const {
  if (!getASTContext().getLangOpts().CPlusPlus)
    return getNumParams();

  // Note that it is possible for a parameter with no default argument to
  // follow a parameter with a default argument.
  unsigned NumRequiredArgs = 0;
  unsigned MinParamsSoFar = 0;
  for (auto *Param : parameters()) {
    if (!Param->isParameterPack()) {
      ++MinParamsSoFar;
      if (!Param->hasDefaultArg())
        NumRequiredArgs = MinParamsSoFar;
    }
  }
  return NumRequiredArgs;
}

bool FunctionDecl::hasOneParamOrDefaultArgs() const {
  return getNumParams() == 1 ||
         (getNumParams() > 1 &&
          std::all_of(param_begin() + 1, param_end(),
                      [](ParmVarDecl *P) { return P->hasDefaultArg(); }));
}

/// The combination of the extern and inline keywords under MSVC forces
/// the function to be required.
///
/// Note: This function assumes that we will only get called when isInlined()
/// would return true for this FunctionDecl.
bool FunctionDecl::isMSExternInline() const {
  assert(isInlined() && "expected to get called on an inlined function!");

  const ASTContext &Context = getASTContext();
  if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
      !hasAttr<DLLExportAttr>())
    return false;

  for (const FunctionDecl *FD = getMostRecentDecl(); FD;
       FD = FD->getPreviousDecl())
    if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
      return true;

  return false;
}

static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) {
  if (Redecl->getStorageClass() != SC_Extern)
    return false;

  for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD;
       FD = FD->getPreviousDecl())
    if (!FD->isImplicit() && FD->getStorageClass() == SC_Extern)
      return false;

  return true;
}

static bool RedeclForcesDefC99(const FunctionDecl *Redecl) {
  // Only consider file-scope declarations in this test.
  if (!Redecl->getLexicalDeclContext()->isTranslationUnit())
    return false;

  // Only consider explicit declarations; the presence of a builtin for a
  // libcall shouldn't affect whether a definition is externally visible.
  if (Redecl->isImplicit())
    return false;

  if (!Redecl->isInlineSpecified() || Redecl->getStorageClass() == SC_Extern)
    return true; // Not an inline definition

  return false;
}

/// For a function declaration in C or C++, determine whether this
/// declaration causes the definition to be externally visible.
///
/// For instance, this determines if adding the current declaration to the set
/// of redeclarations of the given functions causes
/// isInlineDefinitionExternallyVisible to change from false to true.
bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const {
  assert(!doesThisDeclarationHaveABody() &&
         "Must have a declaration without a body.");

  ASTContext &Context = getASTContext();

  if (Context.getLangOpts().MSVCCompat) {
    const FunctionDecl *Definition;
    if (hasBody(Definition) && Definition->isInlined() &&
        redeclForcesDefMSVC(this))
      return true;
  }

  if (Context.getLangOpts().CPlusPlus)
    return false;

  if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
    // With GNU inlining, a declaration with 'inline' but not 'extern', forces
    // an externally visible definition.
    //
    // FIXME: What happens if gnu_inline gets added on after the first
    // declaration?
    if (!isInlineSpecified() || getStorageClass() == SC_Extern)
      return false;

    const FunctionDecl *Prev = this;
    bool FoundBody = false;
    while ((Prev = Prev->getPreviousDecl())) {
      FoundBody |= Prev->doesThisDeclarationHaveABody();

      if (Prev->doesThisDeclarationHaveABody()) {
        // If it's not the case that both 'inline' and 'extern' are
        // specified on the definition, then it is always externally visible.
        if (!Prev->isInlineSpecified() ||
            Prev->getStorageClass() != SC_Extern)
          return false;
      } else if (Prev->isInlineSpecified() &&
                 Prev->getStorageClass() != SC_Extern) {
        return false;
      }
    }
    return FoundBody;
  }

  // C99 6.7.4p6:
  //   [...] If all of the file scope declarations for a function in a
  //   translation unit include the inline function specifier without extern,
  //   then the definition in that translation unit is an inline definition.
  if (isInlineSpecified() && getStorageClass() != SC_Extern)
    return false;
  const FunctionDecl *Prev = this;
  bool FoundBody = false;
  while ((Prev = Prev->getPreviousDecl())) {
    FoundBody |= Prev->doesThisDeclarationHaveABody();
    if (RedeclForcesDefC99(Prev))
      return false;
  }
  return FoundBody;
}

FunctionTypeLoc FunctionDecl::getFunctionTypeLoc() const {
  const TypeSourceInfo *TSI = getTypeSourceInfo();
  return TSI ? TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>()
             : FunctionTypeLoc();
}

SourceRange FunctionDecl::getReturnTypeSourceRange() const {
  FunctionTypeLoc FTL = getFunctionTypeLoc();
  if (!FTL)
    return SourceRange();

  // Skip self-referential return types.
  const SourceManager &SM = getASTContext().getSourceManager();
  SourceRange RTRange = FTL.getReturnLoc().getSourceRange();
  SourceLocation Boundary = getNameInfo().getBeginLoc();
  if (RTRange.isInvalid() || Boundary.isInvalid() ||
      !SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary))
    return SourceRange();

  return RTRange;
}

SourceRange FunctionDecl::getParametersSourceRange() const {
  unsigned NP = getNumParams();
  SourceLocation EllipsisLoc = getEllipsisLoc();

  if (NP == 0 && EllipsisLoc.isInvalid())
    return SourceRange();

  SourceLocation Begin =
      NP > 0 ? ParamInfo[0]->getSourceRange().getBegin() : EllipsisLoc;
  SourceLocation End = EllipsisLoc.isValid()
                           ? EllipsisLoc
                           : ParamInfo[NP - 1]->getSourceRange().getEnd();

  return SourceRange(Begin, End);
}

SourceRange FunctionDecl::getExceptionSpecSourceRange() const {
  FunctionTypeLoc FTL = getFunctionTypeLoc();
  return FTL ? FTL.getExceptionSpecRange() : SourceRange();
}

/// For an inline function definition in C, or for a gnu_inline function
/// in C++, determine whether the definition will be externally visible.
///
/// Inline function definitions are always available for inlining optimizations.
/// However, depending on the language dialect, declaration specifiers, and
/// attributes, the definition of an inline function may or may not be
/// "externally" visible to other translation units in the program.
///
/// In C99, inline definitions are not externally visible by default. However,
/// if even one of the global-scope declarations is marked "extern inline", the
/// inline definition becomes externally visible (C99 6.7.4p6).
///
/// In GNU89 mode, or if the gnu_inline attribute is attached to the function
/// definition, we use the GNU semantics for inline, which are nearly the
/// opposite of C99 semantics. In particular, "inline" by itself will create
/// an externally visible symbol, but "extern inline" will not create an
/// externally visible symbol.
bool FunctionDecl::isInlineDefinitionExternallyVisible() const {
  assert((doesThisDeclarationHaveABody() || willHaveBody() ||
          hasAttr<AliasAttr>()) &&
         "Must be a function definition");
  assert(isInlined() && "Function must be inline");
  ASTContext &Context = getASTContext();

  if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) {
    // Note: If you change the logic here, please change
    // doesDeclarationForceExternallyVisibleDefinition as well.
    //
    // If it's not the case that both 'inline' and 'extern' are
    // specified on the definition, then this inline definition is
    // externally visible.
    if (Context.getLangOpts().CPlusPlus)
      return false;
    if (!(isInlineSpecified() && getStorageClass() == SC_Extern))
      return true;

    // If any declaration is 'inline' but not 'extern', then this definition
    // is externally visible.
    for (auto Redecl : redecls()) {
      if (Redecl->isInlineSpecified() &&
          Redecl->getStorageClass() != SC_Extern)
        return true;
    }

    return false;
  }

  // The rest of this function is C-only.
  assert(!Context.getLangOpts().CPlusPlus &&
         "should not use C inline rules in C++");

  // C99 6.7.4p6:
  //   [...] If all of the file scope declarations for a function in a
  //   translation unit include the inline function specifier without extern,
  //   then the definition in that translation unit is an inline definition.
  for (auto Redecl : redecls()) {
    if (RedeclForcesDefC99(Redecl))
      return true;
  }

  // C99 6.7.4p6:
  //   An inline definition does not provide an external definition for the
  //   function, and does not forbid an external definition in another
  //   translation unit.
  return false;
}

/// getOverloadedOperator - Which C++ overloaded operator this
/// function represents, if any.
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
  if (getDeclName().getNameKind() == DeclarationName::CXXOperatorName)
    return getDeclName().getCXXOverloadedOperator();
  else
    return OO_None;
}

/// getLiteralIdentifier - The literal suffix identifier this function
/// represents, if any.
const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const {
  if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName)
    return getDeclName().getCXXLiteralIdentifier();
  else
    return nullptr;
}

FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const {
  if (TemplateOrSpecialization.isNull())
    return TK_NonTemplate;
  if (TemplateOrSpecialization.is<FunctionTemplateDecl *>())
    return TK_FunctionTemplate;
  if (TemplateOrSpecialization.is<MemberSpecializationInfo *>())
    return TK_MemberSpecialization;
  if (TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>())
    return TK_FunctionTemplateSpecialization;
  if (TemplateOrSpecialization.is
                               <DependentFunctionTemplateSpecializationInfo*>())
    return TK_DependentFunctionTemplateSpecialization;

  llvm_unreachable("Did we miss a TemplateOrSpecialization type?");
}

FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const {
  if (MemberSpecializationInfo *Info = getMemberSpecializationInfo())
    return cast<FunctionDecl>(Info->getInstantiatedFrom());

  return nullptr;
}

MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const {
  if (auto *MSI =
          TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
    return MSI;
  if (auto *FTSI = TemplateOrSpecialization
                       .dyn_cast<FunctionTemplateSpecializationInfo *>())
    return FTSI->getMemberSpecializationInfo();
  return nullptr;
}

void
FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C,
                                               FunctionDecl *FD,
                                               TemplateSpecializationKind TSK) {
  assert(TemplateOrSpecialization.isNull() &&
         "Member function is already a specialization");
  MemberSpecializationInfo *Info
    = new (C) MemberSpecializationInfo(FD, TSK);
  TemplateOrSpecialization = Info;
}

FunctionTemplateDecl *FunctionDecl::getDescribedFunctionTemplate() const {
  return TemplateOrSpecialization.dyn_cast<FunctionTemplateDecl *>();
}

void FunctionDecl::setDescribedFunctionTemplate(FunctionTemplateDecl *Template) {
  assert(TemplateOrSpecialization.isNull() &&
         "Member function is already a specialization");
  TemplateOrSpecialization = Template;
}

bool FunctionDecl::isImplicitlyInstantiable() const {
  // If the function is invalid, it can't be implicitly instantiated.
  if (isInvalidDecl())
    return false;

  switch (getTemplateSpecializationKindForInstantiation()) {
  case TSK_Undeclared:
  case TSK_ExplicitInstantiationDefinition:
  case TSK_ExplicitSpecialization:
    return false;

  case TSK_ImplicitInstantiation:
    return true;

  case TSK_ExplicitInstantiationDeclaration:
    // Handled below.
    break;
  }

  // Find the actual template from which we will instantiate.
  const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
  bool HasPattern = false;
  if (PatternDecl)
    HasPattern = PatternDecl->hasBody(PatternDecl);

  // C++0x [temp.explicit]p9:
  //   Except for inline functions, other explicit instantiation declarations
  //   have the effect of suppressing the implicit instantiation of the entity
  //   to which they refer.
  if (!HasPattern || !PatternDecl)
    return true;

  return PatternDecl->isInlined();
}

bool FunctionDecl::isTemplateInstantiation() const {
  // FIXME: Remove this, it's not clear what it means. (Which template
  // specialization kind?)
  return clang::isTemplateInstantiation(getTemplateSpecializationKind());
}

FunctionDecl *
FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
  // If this is a generic lambda call operator specialization, its
  // instantiation pattern is always its primary template's pattern
  // even if its primary template was instantiated from another
  // member template (which happens with nested generic lambdas).
  // Since a lambda's call operator's body is transformed eagerly,
  // we don't have to go hunting for a prototype definition template
  // (i.e. instantiated-from-member-template) to use as an instantiation
  // pattern.

  if (isGenericLambdaCallOperatorSpecialization(
          dyn_cast<CXXMethodDecl>(this))) {
    assert(getPrimaryTemplate() && "not a generic lambda call operator?");
    return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());
  }

  if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) {
    if (ForDefinition &&
        !clang::isTemplateInstantiation(Info->getTemplateSpecializationKind()))
      return nullptr;
    return getDefinitionOrSelf(cast<FunctionDecl>(Info->getInstantiatedFrom()));
  }

  if (ForDefinition &&
      !clang::isTemplateInstantiation(getTemplateSpecializationKind()))
    return nullptr;

  if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
    // If we hit a point where the user provided a specialization of this
    // template, we're done looking.
    while (!ForDefinition || !Primary->isMemberSpecialization()) {
      auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
      if (!NewPrimary)
        break;
      Primary = NewPrimary;
    }

    return getDefinitionOrSelf(Primary->getTemplatedDecl());
  }

  return nullptr;
}

FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
  if (FunctionTemplateSpecializationInfo *Info
        = TemplateOrSpecialization
            .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
    return Info->getTemplate();
  }
  return nullptr;
}

FunctionTemplateSpecializationInfo *
FunctionDecl::getTemplateSpecializationInfo() const {
  return TemplateOrSpecialization
      .dyn_cast<FunctionTemplateSpecializationInfo *>();
}

const TemplateArgumentList *
FunctionDecl::getTemplateSpecializationArgs() const {
  if (FunctionTemplateSpecializationInfo *Info
        = TemplateOrSpecialization
            .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
    return Info->TemplateArguments;
  }
  return nullptr;
}

const ASTTemplateArgumentListInfo *
FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
  if (FunctionTemplateSpecializationInfo *Info
        = TemplateOrSpecialization
            .dyn_cast<FunctionTemplateSpecializationInfo*>()) {
    return Info->TemplateArgumentsAsWritten;
  }
  return nullptr;
}

void
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
                                                FunctionTemplateDecl *Template,
                                     const TemplateArgumentList *TemplateArgs,
                                                void *InsertPos,
                                                TemplateSpecializationKind TSK,
                        const TemplateArgumentListInfo *TemplateArgsAsWritten,
                                          SourceLocation PointOfInstantiation) {
  assert((TemplateOrSpecialization.isNull() ||
          TemplateOrSpecialization.is<MemberSpecializationInfo *>()) &&
         "Member function is already a specialization");
  assert(TSK != TSK_Undeclared &&
         "Must specify the type of function template specialization");
  assert((TemplateOrSpecialization.isNull() ||
          TSK == TSK_ExplicitSpecialization) &&
         "Member specialization must be an explicit specialization");
  FunctionTemplateSpecializationInfo *Info =
      FunctionTemplateSpecializationInfo::Create(
          C, this, Template, TSK, TemplateArgs, TemplateArgsAsWritten,
          PointOfInstantiation,
          TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>());
  TemplateOrSpecialization = Info;
  Template->addSpecialization(Info, InsertPos);
}

void
FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
                                    const UnresolvedSetImpl &Templates,
                             const TemplateArgumentListInfo &TemplateArgs) {
  assert(TemplateOrSpecialization.isNull());
  DependentFunctionTemplateSpecializationInfo *Info =
      DependentFunctionTemplateSpecializationInfo::Create(Context, Templates,
                                                          TemplateArgs);
  TemplateOrSpecialization = Info;
}

DependentFunctionTemplateSpecializationInfo *
FunctionDecl::getDependentSpecializationInfo() const {
  return TemplateOrSpecialization
      .dyn_cast<DependentFunctionTemplateSpecializationInfo *>();
}

DependentFunctionTemplateSpecializationInfo *
DependentFunctionTemplateSpecializationInfo::Create(
    ASTContext &Context, const UnresolvedSetImpl &Ts,
    const TemplateArgumentListInfo &TArgs) {
  void *Buffer = Context.Allocate(
      totalSizeToAlloc<TemplateArgumentLoc, FunctionTemplateDecl *>(
          TArgs.size(), Ts.size()));
  return new (Buffer) DependentFunctionTemplateSpecializationInfo(Ts, TArgs);
}

DependentFunctionTemplateSpecializationInfo::
DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
                                      const TemplateArgumentListInfo &TArgs)
  : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
  NumTemplates = Ts.size();
  NumArgs = TArgs.size();

  FunctionTemplateDecl **TsArray = getTrailingObjects<FunctionTemplateDecl *>();
  for (unsigned I = 0, E = Ts.size(); I != E; ++I)
    TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl());

  TemplateArgumentLoc *ArgsArray = getTrailingObjects<TemplateArgumentLoc>();
  for (unsigned I = 0, E = TArgs.size(); I != E; ++I)
    new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]);
}

TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
  // For a function template specialization, query the specialization
  // information object.
  if (FunctionTemplateSpecializationInfo *FTSInfo =
          TemplateOrSpecialization
              .dyn_cast<FunctionTemplateSpecializationInfo *>())
    return FTSInfo->getTemplateSpecializationKind();

  if (MemberSpecializationInfo *MSInfo =
          TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
    return MSInfo->getTemplateSpecializationKind();

  return TSK_Undeclared;
}

TemplateSpecializationKind
FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
  // This is the same as getTemplateSpecializationKind(), except that for a
  // function that is both a function template specialization and a member
  // specialization, we prefer the member specialization information. Eg:
  //
  // template<typename T> struct A {
  //   template<typename U> void f() {}
  //   template<> void f<int>() {}
  // };
  //
  // For A<int>::f<int>():
  // * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization
  // * getTemplateSpecializationKindForInstantiation() will return
  //       TSK_ImplicitInstantiation
  //
  // This reflects the facts that A<int>::f<int> is an explicit specialization
  // of A<int>::f, and that A<int>::f<int> should be implicitly instantiated
  // from A::f<int> if a definition is needed.
  if (FunctionTemplateSpecializationInfo *FTSInfo =
          TemplateOrSpecialization
              .dyn_cast<FunctionTemplateSpecializationInfo *>()) {
    if (auto *MSInfo = FTSInfo->getMemberSpecializationInfo())
      return MSInfo->getTemplateSpecializationKind();
    return FTSInfo->getTemplateSpecializationKind();
  }

  if (MemberSpecializationInfo *MSInfo =
          TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
    return MSInfo->getTemplateSpecializationKind();

  return TSK_Undeclared;
}

void
FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
                                          SourceLocation PointOfInstantiation) {
  if (FunctionTemplateSpecializationInfo *FTSInfo
        = TemplateOrSpecialization.dyn_cast<
                                    FunctionTemplateSpecializationInfo*>()) {
    FTSInfo->setTemplateSpecializationKind(TSK);
    if (TSK != TSK_ExplicitSpecialization &&
        PointOfInstantiation.isValid() &&
        FTSInfo->getPointOfInstantiation().isInvalid()) {
      FTSInfo->setPointOfInstantiation(PointOfInstantiation);
      if (ASTMutationListener *L = getASTContext().getASTMutationListener())
        L->InstantiationRequested(this);
    }
  } else if (MemberSpecializationInfo *MSInfo
             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {
    MSInfo->setTemplateSpecializationKind(TSK);
    if (TSK != TSK_ExplicitSpecialization &&
        PointOfInstantiation.isValid() &&
        MSInfo->getPointOfInstantiation().isInvalid()) {
      MSInfo->setPointOfInstantiation(PointOfInstantiation);
      if (ASTMutationListener *L = getASTContext().getASTMutationListener())
        L->InstantiationRequested(this);
    }
  } else
    llvm_unreachable("Function cannot have a template specialization kind");
}

SourceLocation FunctionDecl::getPointOfInstantiation() const {
  if (FunctionTemplateSpecializationInfo *FTSInfo
        = TemplateOrSpecialization.dyn_cast<
                                        FunctionTemplateSpecializationInfo*>())
    return FTSInfo->getPointOfInstantiation();
  else if (MemberSpecializationInfo *MSInfo
             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>())
    return MSInfo->getPointOfInstantiation();

  return SourceLocation();
}

bool FunctionDecl::isOutOfLine() const {
  if (Decl::isOutOfLine())
    return true;

  // If this function was instantiated from a member function of a
  // class template, check whether that member function was defined out-of-line.
  if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
    const FunctionDecl *Definition;
    if (FD->hasBody(Definition))
      return Definition->isOutOfLine();
  }

  // If this function was instantiated from a function template,
  // check whether that function template was defined out-of-line.
  if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
    const FunctionDecl *Definition;
    if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
      return Definition->isOutOfLine();
  }

  return false;
}

SourceRange FunctionDecl::getSourceRange() const {
  return SourceRange(getOuterLocStart(), EndRangeLoc);
}

unsigned FunctionDecl::getMemoryFunctionKind() const {
  IdentifierInfo *FnInfo = getIdentifier();

  if (!FnInfo)
    return 0;

  // Builtin handling.
  switch (getBuiltinID()) {
  case Builtin::BI__builtin_memset:
  case Builtin::BI__builtin___memset_chk:
  case Builtin::BImemset:
    return Builtin::BImemset;

  case Builtin::BI__builtin_memcpy:
  case Builtin::BI__builtin___memcpy_chk:
  case Builtin::BImemcpy:
    return Builtin::BImemcpy;

  case Builtin::BI__builtin_mempcpy:
  case Builtin::BI__builtin___mempcpy_chk:
  case Builtin::BImempcpy:
    return Builtin::BImempcpy;

  case Builtin::BI__builtin_memmove:
  case Builtin::BI__builtin___memmove_chk:
  case Builtin::BImemmove:
    return Builtin::BImemmove;

  case Builtin::BIstrlcpy:
  case Builtin::BI__builtin___strlcpy_chk:
    return Builtin::BIstrlcpy;

  case Builtin::BIstrlcat:
  case Builtin::BI__builtin___strlcat_chk:
    return Builtin::BIstrlcat;

  case Builtin::BI__builtin_memcmp:
  case Builtin::BImemcmp:
    return Builtin::BImemcmp;

  case Builtin::BI__builtin_bcmp:
  case Builtin::BIbcmp:
    return Builtin::BIbcmp;

  case Builtin::BI__builtin_strncpy:
  case Builtin::BI__builtin___strncpy_chk:
  case Builtin::BIstrncpy:
    return Builtin::BIstrncpy;

  case Builtin::BI__builtin_strncmp:
  case Builtin::BIstrncmp:
    return Builtin::BIstrncmp;

  case Builtin::BI__builtin_strncasecmp:
  case Builtin::BIstrncasecmp:
    return Builtin::BIstrncasecmp;

  case Builtin::BI__builtin_strncat:
  case Builtin::BI__builtin___strncat_chk:
  case Builtin::BIstrncat:
    return Builtin::BIstrncat;

  case Builtin::BI__builtin_strndup:
  case Builtin::BIstrndup:
    return Builtin::BIstrndup;

  case Builtin::BI__builtin_strlen:
  case Builtin::BIstrlen:
    return Builtin::BIstrlen;

  case Builtin::BI__builtin_bzero:
  case Builtin::BIbzero:
    return Builtin::BIbzero;

  default:
    if (isExternC()) {
      if (FnInfo->isStr("memset"))
        return Builtin::BImemset;
      else if (FnInfo->isStr("memcpy"))
        return Builtin::BImemcpy;
      else if (FnInfo->isStr("mempcpy"))
        return Builtin::BImempcpy;
      else if (FnInfo->isStr("memmove"))
        return Builtin::BImemmove;
      else if (FnInfo->isStr("memcmp"))
        return Builtin::BImemcmp;
      else if (FnInfo->isStr("bcmp"))
        return Builtin::BIbcmp;
      else if (FnInfo->isStr("strncpy"))
        return Builtin::BIstrncpy;
      else if (FnInfo->isStr("strncmp"))
        return Builtin::BIstrncmp;
      else if (FnInfo->isStr("strncasecmp"))
        return Builtin::BIstrncasecmp;
      else if (FnInfo->isStr("strncat"))
        return Builtin::BIstrncat;
      else if (FnInfo->isStr("strndup"))
        return Builtin::BIstrndup;
      else if (FnInfo->isStr("strlen"))
        return Builtin::BIstrlen;
      else if (FnInfo->isStr("bzero"))
        return Builtin::BIbzero;
    }
    break;
  }
  return 0;
}

unsigned FunctionDecl::getODRHash() const {
  assert(hasODRHash());
  return ODRHash;
}

unsigned FunctionDecl::getODRHash() {
  if (hasODRHash())
    return ODRHash;

  if (auto *FT = getInstantiatedFromMemberFunction()) {
    setHasODRHash(true);
    ODRHash = FT->getODRHash();
    return ODRHash;
  }

  class ODRHash Hash;
  Hash.AddFunctionDecl(this);
  setHasODRHash(true);
  ODRHash = Hash.CalculateHash();
  return ODRHash;
}

//===----------------------------------------------------------------------===//
// FieldDecl Implementation
//===----------------------------------------------------------------------===//

FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC,
                             SourceLocation StartLoc, SourceLocation IdLoc,
                             IdentifierInfo *Id, QualType T,
                             TypeSourceInfo *TInfo, Expr *BW, bool Mutable,
                             InClassInitStyle InitStyle) {
  return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo,
                               BW, Mutable, InitStyle);
}

FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(),
                               SourceLocation(), nullptr, QualType(), nullptr,
                               nullptr, false, ICIS_NoInit);
}

bool FieldDecl::isAnonymousStructOrUnion() const {
  if (!isImplicit() || getDeclName())
    return false;

  if (const auto *Record = getType()->getAs<RecordType>())
    return Record->getDecl()->isAnonymousStructOrUnion();

  return false;
}

unsigned FieldDecl::getBitWidthValue(const ASTContext &Ctx) const {
  assert(isBitField() && "not a bitfield");
  return getBitWidth()->EvaluateKnownConstInt(Ctx).getZExtValue();
}

bool FieldDecl::isZeroLengthBitField(const ASTContext &Ctx) const {
  return isUnnamedBitfield() && !getBitWidth()->isValueDependent() &&
         getBitWidthValue(Ctx) == 0;
}

bool FieldDecl::isZeroSize(const ASTContext &Ctx) const {
  if (isZeroLengthBitField(Ctx))
    return true;

  // C++2a [intro.object]p7:
  //   An object has nonzero size if it
  //     -- is not a potentially-overlapping subobject, or
  if (!hasAttr<NoUniqueAddressAttr>())
    return false;

  //     -- is not of class type, or
  const auto *RT = getType()->getAs<RecordType>();
  if (!RT)
    return false;
  const RecordDecl *RD = RT->getDecl()->getDefinition();
  if (!RD) {
    assert(isInvalidDecl() && "valid field has incomplete type");
    return false;
  }

  //     -- [has] virtual member functions or virtual base classes, or
  //     -- has subobjects of nonzero size or bit-fields of nonzero length
  const auto *CXXRD = cast<CXXRecordDecl>(RD);
  if (!CXXRD->isEmpty())
    return false;

  // Otherwise, [...] the circumstances under which the object has zero size
  // are implementation-defined.
  // FIXME: This might be Itanium ABI specific; we don't yet know what the MS
  // ABI will do.
  return true;
}

unsigned FieldDecl::getFieldIndex() const {
  const FieldDecl *Canonical = getCanonicalDecl();
  if (Canonical != this)
    return Canonical->getFieldIndex();

  if (CachedFieldIndex) return CachedFieldIndex - 1;

  unsigned Index = 0;
  const RecordDecl *RD = getParent()->getDefinition();
  assert(RD && "requested index for field of struct with no definition");

  for (auto *Field : RD->fields()) {
    Field->getCanonicalDecl()->CachedFieldIndex = Index + 1;
    ++Index;
  }

  assert(CachedFieldIndex && "failed to find field in parent");
  return CachedFieldIndex - 1;
}

SourceRange FieldDecl::getSourceRange() const {
  const Expr *FinalExpr = getInClassInitializer();
  if (!FinalExpr)
    FinalExpr = getBitWidth();
  if (FinalExpr)
    return SourceRange(getInnerLocStart(), FinalExpr->getEndLoc());
  return DeclaratorDecl::getSourceRange();
}

void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
  assert((getParent()->isLambda() || getParent()->isCapturedRecord()) &&
         "capturing type in non-lambda or captured record.");
  assert(InitStorage.getInt() == ISK_NoInit &&
         InitStorage.getPointer() == nullptr &&
         "bit width, initializer or captured type already set");
  InitStorage.setPointerAndInt(const_cast<VariableArrayType *>(VLAType),
                               ISK_CapturedVLAType);
}

//===----------------------------------------------------------------------===//
// TagDecl Implementation
//===----------------------------------------------------------------------===//

TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
                 SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
                 SourceLocation StartL)
    : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C),
      TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
  assert((DK != Enum || TK == TTK_Enum) &&
         "EnumDecl not matched with TTK_Enum");
  setPreviousDecl(PrevDecl);
  setTagKind(TK);
  setCompleteDefinition(false);
  setBeingDefined(false);
  setEmbeddedInDeclarator(false);
  setFreeStanding(false);
  setCompleteDefinitionRequired(false);
}

SourceLocation TagDecl::getOuterLocStart() const {
  return getTemplateOrInnerLocStart(this);
}

SourceRange TagDecl::getSourceRange() const {
  SourceLocation RBraceLoc = BraceRange.getEnd();
  SourceLocation E = RBraceLoc.isValid() ? RBraceLoc : getLocation();
  return SourceRange(getOuterLocStart(), E);
}

TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); }

void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
  TypedefNameDeclOrQualifier = TDD;
  if (const Type *T = getTypeForDecl()) {
    (void)T;
    assert(T->isLinkageValid());
  }
  assert(isLinkageValid());
}

void TagDecl::startDefinition() {
  setBeingDefined(true);

  if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
    struct CXXRecordDecl::DefinitionData *Data =
      new (getASTContext()) struct CXXRecordDecl::DefinitionData(D);
    for (auto I : redecls())
      cast<CXXRecordDecl>(I)->DefinitionData = Data;
  }
}

void TagDecl::completeDefinition() {
  assert((!isa<CXXRecordDecl>(this) ||
          cast<CXXRecordDecl>(this)->hasDefinition()) &&
         "definition completed but not started");

  setCompleteDefinition(true);
  setBeingDefined(false);

  if (ASTMutationListener *L = getASTMutationListener())
    L->CompletedTagDefinition(this);
}

TagDecl *TagDecl::getDefinition() const {
  if (isCompleteDefinition())
    return const_cast<TagDecl *>(this);

  // If it's possible for us to have an out-of-date definition, check now.
  if (mayHaveOutOfDateDef()) {
    if (IdentifierInfo *II = getIdentifier()) {
      if (II->isOutOfDate()) {
        updateOutOfDate(*II);
      }
    }
  }

  if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(this))
    return CXXRD->getDefinition();

  for (auto R : redecls())
    if (R->isCompleteDefinition())
      return R;

  return nullptr;
}

void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
  if (QualifierLoc) {
    // Make sure the extended qualifier info is allocated.
    if (!hasExtInfo())
      TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
    // Set qualifier info.
    getExtInfo()->QualifierLoc = QualifierLoc;
  } else {
    // Here Qualifier == 0, i.e., we are removing the qualifier (if any).
    if (hasExtInfo()) {
      if (getExtInfo()->NumTemplParamLists == 0) {
        getASTContext().Deallocate(getExtInfo());
        TypedefNameDeclOrQualifier = (TypedefNameDecl *)nullptr;
      }
      else
        getExtInfo()->QualifierLoc = QualifierLoc;
    }
  }
}

void TagDecl::setTemplateParameterListsInfo(
    ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists) {
  assert(!TPLists.empty());
  // Make sure the extended decl info is allocated.
  if (!hasExtInfo())
    // Allocate external info struct.
    TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo;
  // Set the template parameter lists info.
  getExtInfo()->setTemplateParameterListsInfo(Context, TPLists);
}

//===----------------------------------------------------------------------===//
// EnumDecl Implementation
//===----------------------------------------------------------------------===//

EnumDecl::EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
                   SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
                   bool Scoped, bool ScopedUsingClassTag, bool Fixed)
    : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
  assert(Scoped || !ScopedUsingClassTag);
  IntegerType = nullptr;
  setNumPositiveBits(0);
  setNumNegativeBits(0);
  setScoped(Scoped);
  setScopedUsingClassTag(ScopedUsingClassTag);
  setFixed(Fixed);
  setHasODRHash(false);
  ODRHash = 0;
}

void EnumDecl::anchor() {}

EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
                           SourceLocation StartLoc, SourceLocation IdLoc,
                           IdentifierInfo *Id,
                           EnumDecl *PrevDecl, bool IsScoped,
                           bool IsScopedUsingClassTag, bool IsFixed) {
  auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
                                    IsScoped, IsScopedUsingClassTag, IsFixed);
  Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
  C.getTypeDeclType(Enum, PrevDecl);
  return Enum;
}

EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  EnumDecl *Enum =
      new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
                           nullptr, nullptr, false, false, false);
  Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
  return Enum;
}

SourceRange EnumDecl::getIntegerTypeRange() const {
  if (const TypeSourceInfo *TI = getIntegerTypeSourceInfo())
    return TI->getTypeLoc().getSourceRange();
  return SourceRange();
}

void EnumDecl::completeDefinition(QualType NewType,
                                  QualType NewPromotionType,
                                  unsigned NumPositiveBits,
                                  unsigned NumNegativeBits) {
  assert(!isCompleteDefinition() && "Cannot redefine enums!");
  if (!IntegerType)
    IntegerType = NewType.getTypePtr();
  PromotionType = NewPromotionType;
  setNumPositiveBits(NumPositiveBits);
  setNumNegativeBits(NumNegativeBits);
  TagDecl::completeDefinition();
}

bool EnumDecl::isClosed() const {
  if (const auto *A = getAttr<EnumExtensibilityAttr>())
    return A->getExtensibility() == EnumExtensibilityAttr::Closed;
  return true;
}

bool EnumDecl::isClosedFlag() const {
  return isClosed() && hasAttr<FlagEnumAttr>();
}

bool EnumDecl::isClosedNonFlag() const {
  return isClosed() && !hasAttr<FlagEnumAttr>();
}

TemplateSpecializationKind EnumDecl::getTemplateSpecializationKind() const {
  if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo())
    return MSI->getTemplateSpecializationKind();

  return TSK_Undeclared;
}

void EnumDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK,
                                         SourceLocation PointOfInstantiation) {
  MemberSpecializationInfo *MSI = getMemberSpecializationInfo();
  assert(MSI && "Not an instantiated member enumeration?");
  MSI->setTemplateSpecializationKind(TSK);
  if (TSK != TSK_ExplicitSpecialization &&
      PointOfInstantiation.isValid() &&
      MSI->getPointOfInstantiation().isInvalid())
    MSI->setPointOfInstantiation(PointOfInstantiation);
}

EnumDecl *EnumDecl::getTemplateInstantiationPattern() const {
  if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
    if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
      EnumDecl *ED = getInstantiatedFromMemberEnum();
      while (auto *NewED = ED->getInstantiatedFromMemberEnum())
        ED = NewED;
      return getDefinitionOrSelf(ED);
    }
  }

  assert(!isTemplateInstantiation(getTemplateSpecializationKind()) &&
         "couldn't find pattern for enum instantiation");
  return nullptr;
}

EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const {
  if (SpecializationInfo)
    return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom());

  return nullptr;
}

void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
                                            TemplateSpecializationKind TSK) {
  assert(!SpecializationInfo && "Member enum is already a specialization");
  SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK);
}

unsigned EnumDecl::getODRHash() {
  if (hasODRHash())
    return ODRHash;

  class ODRHash Hash;
  Hash.AddEnumDecl(this);
  setHasODRHash(true);
  ODRHash = Hash.CalculateHash();
  return ODRHash;
}

//===----------------------------------------------------------------------===//
// RecordDecl Implementation
//===----------------------------------------------------------------------===//

RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
                       DeclContext *DC, SourceLocation StartLoc,
                       SourceLocation IdLoc, IdentifierInfo *Id,
                       RecordDecl *PrevDecl)
    : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
  assert(classof(static_cast<Decl *>(this)) && "Invalid Kind!");
  setHasFlexibleArrayMember(false);
  setAnonymousStructOrUnion(false);
  setHasObjectMember(false);
  setHasVolatileMember(false);
  setHasLoadedFieldsFromExternalStorage(false);
  setNonTrivialToPrimitiveDefaultInitialize(false);
  setNonTrivialToPrimitiveCopy(false);
  setNonTrivialToPrimitiveDestroy(false);
  setHasNonTrivialToPrimitiveDefaultInitializeCUnion(false);
  setHasNonTrivialToPrimitiveDestructCUnion(false);
  setHasNonTrivialToPrimitiveCopyCUnion(false);
  setParamDestroyedInCallee(false);
  setArgPassingRestrictions(APK_CanPassInRegs);
}

RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
                               SourceLocation StartLoc, SourceLocation IdLoc,
                               IdentifierInfo *Id, RecordDecl* PrevDecl) {
  RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
                                         StartLoc, IdLoc, Id, PrevDecl);
  R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);

  C.getTypeDeclType(R, PrevDecl);
  return R;
}

RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
  RecordDecl *R =
      new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(),
                             SourceLocation(), nullptr, nullptr);
  R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
  return R;
}

bool RecordDecl::isInjectedClassName() const {
  return isImplicit() && getDeclName() && getDeclContext()->isRecord() &&
    cast<RecordDecl>(getDeclContext())->getDeclName() == getDeclName();
}

bool RecordDecl::isLambda() const {
  if (auto RD = dyn_cast<CXXRecordDecl>(this))
    return RD->isLambda();
  return false;
}

bool RecordDecl::isCapturedRecord() const {
  return hasAttr<CapturedRecordAttr>();
}

void RecordDecl::setCapturedRecord() {
  addAttr(CapturedRecordAttr::CreateImplicit(getASTContext()));
}

bool RecordDecl::isOrContainsUnion() const {
  if (isUnion())
    return true;

  if (const RecordDecl *Def = getDefinition()) {
    for (const FieldDecl *FD : Def->fields()) {
      const RecordType *RT = FD->getType()->getAs<RecordType>();
      if (RT && RT->getDecl()->isOrContainsUnion())
        return true;
    }
  }

  return false;
}

RecordDecl::field_iterator RecordDecl::field_begin() const {
  if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage())
    LoadFieldsFromExternalStorage();

  return field_iterator(decl_iterator(FirstDecl));
}

/// completeDefinition - Notes that the definition of this type is now
/// complete.
void RecordDecl::completeDefinition() {
  assert(!isCompleteDefinition() && "Cannot redefine record!");
  TagDecl::completeDefinition();
}

/// isMsStruct - Get whether or not this record uses ms_struct layout.
/// This which can be turned on with an attribute, pragma, or the
/// -mms-bitfields command-line option.
bool RecordDecl::isMsStruct(const ASTContext &C) const {
  return hasAttr<MSStructAttr>() || C.getLangOpts().MSBitfields == 1;
}

void RecordDecl::LoadFieldsFromExternalStorage() const {
  ExternalASTSource *Source = getASTContext().getExternalSource();
  assert(hasExternalLexicalStorage() && Source && "No external storage?");

  // Notify that we have a RecordDecl doing some initialization.
  ExternalASTSource::Deserializing TheFields(Source);

  SmallVector<Decl*, 64> Decls;
  setHasLoadedFieldsFromExternalStorage(true);
  Source->FindExternalLexicalDecls(this, [](Decl::Kind K) {
    return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
  }, Decls);

#ifndef NDEBUG
  // Check that all decls we got were FieldDecls.
  for (unsigned i=0, e=Decls.size(); i != e; ++i)
    assert(isa<FieldDecl>(Decls[i]) || isa<IndirectFieldDecl>(Decls[i]));
#endif

  if (Decls.empty())
    return;

  std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls,
                                                 /*FieldsAlreadyLoaded=*/false);
}

bool RecordDecl::mayInsertExtraPadding(bool EmitRemark) const {
  ASTContext &Context = getASTContext();
  const SanitizerMask EnabledAsanMask = Context.getLangOpts().Sanitize.Mask &
      (SanitizerKind::Address | SanitizerKind::KernelAddress);
  if (!EnabledAsanMask || !Context.getLangOpts().SanitizeAddressFieldPadding)
    return false;
  const auto &Blacklist = Context.getSanitizerBlacklist();
  const auto *CXXRD = dyn_cast<CXXRecordDecl>(this);
  // We may be able to relax some of these requirements.
  int ReasonToReject = -1;
  if (!CXXRD || CXXRD->isExternCContext())
    ReasonToReject = 0;  // is not C++.
  else if (CXXRD->hasAttr<PackedAttr>())
    ReasonToReject = 1;  // is packed.
  else if (CXXRD->isUnion())
    ReasonToReject = 2;  // is a union.
  else if (CXXRD->isTriviallyCopyable())
    ReasonToReject = 3;  // is trivially copyable.
  else if (CXXRD->hasTrivialDestructor())
    ReasonToReject = 4;  // has trivial destructor.
  else if (CXXRD->isStandardLayout())
    ReasonToReject = 5;  // is standard layout.
  else if (Blacklist.isBlacklistedLocation(EnabledAsanMask, getLocation(),
                                           "field-padding"))
    ReasonToReject = 6;  // is in an excluded file.
  else if (Blacklist.isBlacklistedType(EnabledAsanMask,
                                       getQualifiedNameAsString(),
                                       "field-padding"))
    ReasonToReject = 7;  // The type is excluded.

  if (EmitRemark) {
    if (ReasonToReject >= 0)
      Context.getDiagnostics().Report(
          getLocation(),
          diag::remark_sanitize_address_insert_extra_padding_rejected)
          << getQualifiedNameAsString() << ReasonToReject;
    else
      Context.getDiagnostics().Report(
          getLocation(),
          diag::remark_sanitize_address_insert_extra_padding_accepted)
          << getQualifiedNameAsString();
  }
  return ReasonToReject < 0;
}

const FieldDecl *RecordDecl::findFirstNamedDataMember() const {
  for (const auto *I : fields()) {
    if (I->getIdentifier())
      return I;

    if (const auto *RT = I->getType()->getAs<RecordType>())
      if (const FieldDecl *NamedDataMember =
              RT->getDecl()->findFirstNamedDataMember())
        return NamedDataMember;
  }

  // We didn't find a named data member.
  return nullptr;
}

//===----------------------------------------------------------------------===//
// BlockDecl Implementation
//===----------------------------------------------------------------------===//

BlockDecl::BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
    : Decl(Block, DC, CaretLoc), DeclContext(Block) {
  setIsVariadic(false);
  setCapturesCXXThis(false);
  setBlockMissingReturnType(true);
  setIsConversionFromLambda(false);
  setDoesNotEscape(false);
  setCanAvoidCopyToHeap(false);
}

void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) {
  assert(!ParamInfo && "Already has param info!");

  // Zero params -> null pointer.
  if (!NewParamInfo.empty()) {
    NumParams = NewParamInfo.size();
    ParamInfo = new (getASTContext()) ParmVarDecl*[NewParamInfo.size()];
    std::copy(NewParamInfo.begin(), NewParamInfo.end(), ParamInfo);
  }
}

void BlockDecl::setCaptures(ASTContext &Context, ArrayRef<Capture> Captures,
                            bool CapturesCXXThis) {
  this->setCapturesCXXThis(CapturesCXXThis);
  this->NumCaptures = Captures.size();

  if (Captures.empty()) {
    this->Captures = nullptr;
    return;
  }

  this->Captures = Captures.copy(Context).data();
}

bool BlockDecl::capturesVariable(const VarDecl *variable) const {
  for (const auto &I : captures())
    // Only auto vars can be captured, so no redeclaration worries.
    if (I.getVariable() == variable)
      return true;

  return false;
}

SourceRange BlockDecl::getSourceRange() const {
  return SourceRange(getLocation(), Body ? Body->getEndLoc() : getLocation());
}

//===----------------------------------------------------------------------===//
// Other Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//

void TranslationUnitDecl::anchor() {}

TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) {
  return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C);
}

void PragmaCommentDecl::anchor() {}

PragmaCommentDecl *PragmaCommentDecl::Create(const ASTContext &C,
                                             TranslationUnitDecl *DC,
                                             SourceLocation CommentLoc,
                                             PragmaMSCommentKind CommentKind,
                                             StringRef Arg) {
  PragmaCommentDecl *PCD =
      new (C, DC, additionalSizeToAlloc<char>(Arg.size() + 1))
          PragmaCommentDecl(DC, CommentLoc, CommentKind);
  memcpy(PCD->getTrailingObjects<char>(), Arg.data(), Arg.size());
  PCD->getTrailingObjects<char>()[Arg.size()] = '\0';
  return PCD;
}

PragmaCommentDecl *PragmaCommentDecl::CreateDeserialized(ASTContext &C,
                                                         unsigned ID,
                                                         unsigned ArgSize) {
  return new (C, ID, additionalSizeToAlloc<char>(ArgSize + 1))
      PragmaCommentDecl(nullptr, SourceLocation(), PCK_Unknown);
}

void PragmaDetectMismatchDecl::anchor() {}

PragmaDetectMismatchDecl *
PragmaDetectMismatchDecl::Create(const ASTContext &C, TranslationUnitDecl *DC,
                                 SourceLocation Loc, StringRef Name,
                                 StringRef Value) {
  size_t ValueStart = Name.size() + 1;
  PragmaDetectMismatchDecl *PDMD =
      new (C, DC, additionalSizeToAlloc<char>(ValueStart + Value.size() + 1))
          PragmaDetectMismatchDecl(DC, Loc, ValueStart);
  memcpy(PDMD->getTrailingObjects<char>(), Name.data(), Name.size());
  PDMD->getTrailingObjects<char>()[Name.size()] = '\0';
  memcpy(PDMD->getTrailingObjects<char>() + ValueStart, Value.data(),
         Value.size());
  PDMD->getTrailingObjects<char>()[ValueStart + Value.size()] = '\0';
  return PDMD;
}

PragmaDetectMismatchDecl *
PragmaDetectMismatchDecl::CreateDeserialized(ASTContext &C, unsigned ID,
                                             unsigned NameValueSize) {
  return new (C, ID, additionalSizeToAlloc<char>(NameValueSize + 1))
      PragmaDetectMismatchDecl(nullptr, SourceLocation(), 0);
}

void ExternCContextDecl::anchor() {}

ExternCContextDecl *ExternCContextDecl::Create(const ASTContext &C,
                                               TranslationUnitDecl *DC) {
  return new (C, DC) ExternCContextDecl(DC);
}

void LabelDecl::anchor() {}

LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
                             SourceLocation IdentL, IdentifierInfo *II) {
  return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, IdentL);
}

LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC,
                             SourceLocation IdentL, IdentifierInfo *II,
                             SourceLocation GnuLabelL) {
  assert(GnuLabelL != IdentL && "Use this only for GNU local labels");
  return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL);
}

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

void LabelDecl::setMSAsmLabel(StringRef Name) {
char *Buffer = new (getASTContext(), 1) char[Name.size() + 1];
  memcpy(Buffer, Name.data(), Name.size());
  Buffer[Name.size()] = '\0';
  MSAsmName = Buffer;
}

void ValueDecl::anchor() {}

bool ValueDecl::isWeak() const {
  for (const auto *I : attrs())
    if (isa<WeakAttr>(I) || isa<WeakRefAttr>(I))
      return true;

  return isWeakImported();
}

void ImplicitParamDecl::anchor() {}

ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC,
                                             SourceLocation IdLoc,
                                             IdentifierInfo *Id, QualType Type,
                                             ImplicitParamKind ParamKind) {
  return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type, ParamKind);
}

ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, QualType Type,
                                             ImplicitParamKind ParamKind) {
  return new (C, nullptr) ImplicitParamDecl(C, Type, ParamKind);
}

ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C,
                                                         unsigned ID) {
  return new (C, ID) ImplicitParamDecl(C, QualType(), ImplicitParamKind::Other);
}

FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
                                   SourceLocation StartLoc,
                                   const DeclarationNameInfo &NameInfo,
                                   QualType T, TypeSourceInfo *TInfo,
                                   StorageClass SC, bool isInlineSpecified,
                                   bool hasWrittenPrototype,
                                   ConstexprSpecKind ConstexprKind,
                                   Expr *TrailingRequiresClause) {
  FunctionDecl *New =
      new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo,
                               SC, isInlineSpecified, ConstexprKind,
                               TrailingRequiresClause);
  New->setHasWrittenPrototype(hasWrittenPrototype);
  return New;
}

FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) FunctionDecl(Function, C, nullptr, SourceLocation(),
                                  DeclarationNameInfo(), QualType(), nullptr,
                                  SC_None, false, CSK_unspecified, nullptr);
}

BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
  return new (C, DC) BlockDecl(DC, L);
}

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

CapturedDecl::CapturedDecl(DeclContext *DC, unsigned NumParams)
    : Decl(Captured, DC, SourceLocation()), DeclContext(Captured),
      NumParams(NumParams), ContextParam(0), BodyAndNothrow(nullptr, false) {}

CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC,
                                   unsigned NumParams) {
  return new (C, DC, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
      CapturedDecl(DC, NumParams);
}

CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID,
                                               unsigned NumParams) {
  return new (C, ID, additionalSizeToAlloc<ImplicitParamDecl *>(NumParams))
      CapturedDecl(nullptr, NumParams);
}

Stmt *CapturedDecl::getBody() const { return BodyAndNothrow.getPointer(); }
void CapturedDecl::setBody(Stmt *B) { BodyAndNothrow.setPointer(B); }

bool CapturedDecl::isNothrow() const { return BodyAndNothrow.getInt(); }
void CapturedDecl::setNothrow(bool Nothrow) { BodyAndNothrow.setInt(Nothrow); }

EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD,
                                           SourceLocation L,
                                           IdentifierInfo *Id, QualType T,
                                           Expr *E, const llvm::APSInt &V) {
  return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V);
}

EnumConstantDecl *
EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr,
                                      QualType(), nullptr, llvm::APSInt());
}

void IndirectFieldDecl::anchor() {}

IndirectFieldDecl::IndirectFieldDecl(ASTContext &C, DeclContext *DC,
                                     SourceLocation L, DeclarationName N,
                                     QualType T,
                                     MutableArrayRef<NamedDecl *> CH)
    : ValueDecl(IndirectField, DC, L, N, T), Chaining(CH.data()),
      ChainingSize(CH.size()) {
  // In C++, indirect field declarations conflict with tag declarations in the
  // same scope, so add them to IDNS_Tag so that tag redeclaration finds them.
  if (C.getLangOpts().CPlusPlus)
    IdentifierNamespace |= IDNS_Tag;
}

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

IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C,
                                                         unsigned ID) {
  return new (C, ID) IndirectFieldDecl(C, nullptr, SourceLocation(),
                                       DeclarationName(), QualType(), None);
}

SourceRange EnumConstantDecl::getSourceRange() const {
  SourceLocation End = getLocation();
  if (Init)
    End = Init->getEndLoc();
  return SourceRange(getLocation(), End);
}

void TypeDecl::anchor() {}

TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
                                 SourceLocation StartLoc, SourceLocation IdLoc,
                                 IdentifierInfo *Id, TypeSourceInfo *TInfo) {
  return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}

void TypedefNameDecl::anchor() {}

TagDecl *TypedefNameDecl::getAnonDeclWithTypedefName(bool AnyRedecl) const {
  if (auto *TT = getTypeSourceInfo()->getType()->getAs<TagType>()) {
    auto *OwningTypedef = TT->getDecl()->getTypedefNameForAnonDecl();
    auto *ThisTypedef = this;
    if (AnyRedecl && OwningTypedef) {
      OwningTypedef = OwningTypedef->getCanonicalDecl();
      ThisTypedef = ThisTypedef->getCanonicalDecl();
    }
    if (OwningTypedef == ThisTypedef)
      return TT->getDecl();
  }

  return nullptr;
}

bool TypedefNameDecl::isTransparentTagSlow() const {
  auto determineIsTransparent = [&]() {
    if (auto *TT = getUnderlyingType()->getAs<TagType>()) {
      if (auto *TD = TT->getDecl()) {
        if (TD->getName() != getName())
          return false;
        SourceLocation TTLoc = getLocation();
        SourceLocation TDLoc = TD->getLocation();
        if (!TTLoc.isMacroID() || !TDLoc.isMacroID())
          return false;
        SourceManager &SM = getASTContext().getSourceManager();
        return SM.getSpellingLoc(TTLoc) == SM.getSpellingLoc(TDLoc);
      }
    }
    return false;
  };

  bool isTransparent = determineIsTransparent();
  MaybeModedTInfo.setInt((isTransparent << 1) | 1);
  return isTransparent;
}

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

TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC,
                                     SourceLocation StartLoc,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
                                     TypeSourceInfo *TInfo) {
  return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo);
}

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

SourceRange TypedefDecl::getSourceRange() const {
  SourceLocation RangeEnd = getLocation();
  if (TypeSourceInfo *TInfo = getTypeSourceInfo()) {
    if (typeIsPostfix(TInfo->getType()))
      RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
  }
  return SourceRange(getBeginLoc(), RangeEnd);
}

SourceRange TypeAliasDecl::getSourceRange() const {
  SourceLocation RangeEnd = getBeginLoc();
  if (TypeSourceInfo *TInfo = getTypeSourceInfo())
    RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd();
  return SourceRange(getBeginLoc(), RangeEnd);
}

void FileScopeAsmDecl::anchor() {}

FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC,
                                           StringLiteral *Str,
                                           SourceLocation AsmLoc,
                                           SourceLocation RParenLoc) {
  return new (C, DC) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc);
}

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

void EmptyDecl::anchor() {}

EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) {
  return new (C, DC) EmptyDecl(DC, L);
}

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

//===----------------------------------------------------------------------===//
// ImportDecl Implementation
//===----------------------------------------------------------------------===//

/// Retrieve the number of module identifiers needed to name the given
/// module.
static unsigned getNumModuleIdentifiers(Module *Mod) {
  unsigned Result = 1;
  while (Mod->Parent) {
    Mod = Mod->Parent;
    ++Result;
  }
  return Result;
}

ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
                       Module *Imported,
                       ArrayRef<SourceLocation> IdentifierLocs)
    : Decl(Import, DC, StartLoc), ImportedModule(Imported),
      NextLocalImportAndComplete(nullptr, true) {
  assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
  auto *StoredLocs = getTrailingObjects<SourceLocation>();
  std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(),
                          StoredLocs);
}

ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
                       Module *Imported, SourceLocation EndLoc)
    : Decl(Import, DC, StartLoc), ImportedModule(Imported),
      NextLocalImportAndComplete(nullptr, false) {
  *getTrailingObjects<SourceLocation>() = EndLoc;
}

ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC,
                               SourceLocation StartLoc, Module *Imported,
                               ArrayRef<SourceLocation> IdentifierLocs) {
  return new (C, DC,
              additionalSizeToAlloc<SourceLocation>(IdentifierLocs.size()))
      ImportDecl(DC, StartLoc, Imported, IdentifierLocs);
}

ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC,
                                       SourceLocation StartLoc,
                                       Module *Imported,
                                       SourceLocation EndLoc) {
  ImportDecl *Import = new (C, DC, additionalSizeToAlloc<SourceLocation>(1))
      ImportDecl(DC, StartLoc, Imported, EndLoc);
  Import->setImplicit();
  return Import;
}

ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID,
                                           unsigned NumLocations) {
  return new (C, ID, additionalSizeToAlloc<SourceLocation>(NumLocations))
      ImportDecl(EmptyShell());
}

ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
  if (!isImportComplete())
    return None;

  const auto *StoredLocs = getTrailingObjects<SourceLocation>();
  return llvm::makeArrayRef(StoredLocs,
                            getNumModuleIdentifiers(getImportedModule()));
}

SourceRange ImportDecl::getSourceRange() const {
  if (!isImportComplete())
    return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>());

  return SourceRange(getLocation(), getIdentifierLocs().back());
}

//===----------------------------------------------------------------------===//
// ExportDecl Implementation
//===----------------------------------------------------------------------===//

void ExportDecl::anchor() {}

ExportDecl *ExportDecl::Create(ASTContext &C, DeclContext *DC,
                               SourceLocation ExportLoc) {
  return new (C, DC) ExportDecl(DC, ExportLoc);
}

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