//===- DeclCXX.cpp - C++ Declaration AST Node Implementation --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the C++ related Decl classes.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/ASTUnresolvedSet.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/ODRHash.h"
#include "clang/AST/Type.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>

using namespace clang;

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

void AccessSpecDecl::anchor() {}

AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) AccessSpecDecl(EmptyShell());
}

void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const {
  ExternalASTSource *Source = C.getExternalSource();
  assert(Impl.Decls.isLazy() && "getFromExternalSource for non-lazy set");
  assert(Source && "getFromExternalSource with no external source");

  for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I)
    I.setDecl(cast<NamedDecl>(Source->GetExternalDecl(
        reinterpret_cast<uintptr_t>(I.getDecl()) >> 2)));
  Impl.Decls.setLazy(false);
}

CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
    : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0),
      Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false),
      Abstract(false), IsStandardLayout(true), IsCXX11StandardLayout(true),
      HasBasesWithFields(false), HasBasesWithNonStaticDataMembers(false),
      HasPrivateFields(false), HasProtectedFields(false),
      HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false),
      HasOnlyCMembers(true), HasInClassInitializer(false),
      HasUninitializedReferenceMember(false), HasUninitializedFields(false),
      HasInheritedConstructor(false), HasInheritedAssignment(false),
      NeedOverloadResolutionForCopyConstructor(false),
      NeedOverloadResolutionForMoveConstructor(false),
      NeedOverloadResolutionForMoveAssignment(false),
      NeedOverloadResolutionForDestructor(false),
      DefaultedCopyConstructorIsDeleted(false),
      DefaultedMoveConstructorIsDeleted(false),
      DefaultedMoveAssignmentIsDeleted(false),
      DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
      HasTrivialSpecialMembersForCall(SMF_All),
      DeclaredNonTrivialSpecialMembers(0),
      DeclaredNonTrivialSpecialMembersForCall(0), HasIrrelevantDestructor(true),
      HasConstexprNonCopyMoveConstructor(false),
      HasDefaultedDefaultConstructor(false),
      DefaultedDefaultConstructorIsConstexpr(true),
      HasConstexprDefaultConstructor(false),
      HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
      UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
      ImplicitCopyConstructorCanHaveConstParamForVBase(true),
      ImplicitCopyConstructorCanHaveConstParamForNonVBase(true),
      ImplicitCopyAssignmentHasConstParam(true),
      HasDeclaredCopyConstructorWithConstParam(false),
      HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false),
      IsParsingBaseSpecifiers(false), HasODRHash(false), Definition(D) {}

CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const {
  return Bases.get(Definition->getASTContext().getExternalSource());
}

CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase() const {
  return VBases.get(Definition->getASTContext().getExternalSource());
}

CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C,
                             DeclContext *DC, SourceLocation StartLoc,
                             SourceLocation IdLoc, IdentifierInfo *Id,
                             CXXRecordDecl *PrevDecl)
    : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl),
      DefinitionData(PrevDecl ? PrevDecl->DefinitionData
                              : nullptr) {}

CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
                                     DeclContext *DC, SourceLocation StartLoc,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
                                     CXXRecordDecl *PrevDecl,
                                     bool DelayTypeCreation) {
  auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
                                      PrevDecl);
  R->MayHaveOutOfDateDef = C.getLangOpts().Modules;

  // FIXME: DelayTypeCreation seems like such a hack
  if (!DelayTypeCreation)
    C.getTypeDeclType(R, PrevDecl);
  return R;
}

CXXRecordDecl *
CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
                            TypeSourceInfo *Info, SourceLocation Loc,
                            bool Dependent, bool IsGeneric,
                            LambdaCaptureDefault CaptureDefault) {
  auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
                                      nullptr, nullptr);
  R->IsBeingDefined = true;
  R->DefinitionData =
      new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
                                          CaptureDefault);
  R->MayHaveOutOfDateDef = false;
  R->setImplicit(true);
  C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
  return R;
}

CXXRecordDecl *
CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
  auto *R = new (C, ID) CXXRecordDecl(
      CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
      nullptr, nullptr);
  R->MayHaveOutOfDateDef = false;
  return R;
}

/// Determine whether a class has a repeated base class. This is intended for
/// use when determining if a class is standard-layout, so makes no attempt to
/// handle virtual bases.
static bool hasRepeatedBaseClass(const CXXRecordDecl *StartRD) {
  llvm::SmallPtrSet<const CXXRecordDecl*, 8> SeenBaseTypes;
  SmallVector<const CXXRecordDecl*, 8> WorkList = {StartRD};
  while (!WorkList.empty()) {
    const CXXRecordDecl *RD = WorkList.pop_back_val();
    for (const CXXBaseSpecifier &BaseSpec : RD->bases()) {
      if (const CXXRecordDecl *B = BaseSpec.getType()->getAsCXXRecordDecl()) {
        if (!SeenBaseTypes.insert(B).second)
          return true;
        WorkList.push_back(B);
      }
    }
  }
  return false;
}

void
CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
                        unsigned NumBases) {
  ASTContext &C = getASTContext();

  if (!data().Bases.isOffset() && data().NumBases > 0)
    C.Deallocate(data().getBases());

  if (NumBases) {
    if (!C.getLangOpts().CPlusPlus17) {
      // C++ [dcl.init.aggr]p1:
      //   An aggregate is [...] a class with [...] no base classes [...].
      data().Aggregate = false;
    }

    // C++ [class]p4:
    //   A POD-struct is an aggregate class...
    data().PlainOldData = false;
  }

  // The set of seen virtual base types.
  llvm::SmallPtrSet<CanQualType, 8> SeenVBaseTypes;

  // The virtual bases of this class.
  SmallVector<const CXXBaseSpecifier *, 8> VBases;

  data().Bases = new(C) CXXBaseSpecifier [NumBases];
  data().NumBases = NumBases;
  for (unsigned i = 0; i < NumBases; ++i) {
    data().getBases()[i] = *Bases[i];
    // Keep track of inherited vbases for this base class.
    const CXXBaseSpecifier *Base = Bases[i];
    QualType BaseType = Base->getType();
    // Skip dependent types; we can't do any checking on them now.
    if (BaseType->isDependentType())
      continue;
    auto *BaseClassDecl =
        cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());

    // C++2a [class]p7:
    //   A standard-layout class is a class that:
    //    [...]
    //    -- has all non-static data members and bit-fields in the class and
    //       its base classes first declared in the same class
    if (BaseClassDecl->data().HasBasesWithFields ||
        !BaseClassDecl->field_empty()) {
      if (data().HasBasesWithFields)
        // Two bases have members or bit-fields: not standard-layout.
        data().IsStandardLayout = false;
      data().HasBasesWithFields = true;
    }

    // C++11 [class]p7:
    //   A standard-layout class is a class that:
    //     -- [...] has [...] at most one base class with non-static data
    //        members
    if (BaseClassDecl->data().HasBasesWithNonStaticDataMembers ||
        BaseClassDecl->hasDirectFields()) {
      if (data().HasBasesWithNonStaticDataMembers)
        data().IsCXX11StandardLayout = false;
      data().HasBasesWithNonStaticDataMembers = true;
    }

    if (!BaseClassDecl->isEmpty()) {
      // C++14 [meta.unary.prop]p4:
      //   T is a class type [...] with [...] no base class B for which
      //   is_empty<B>::value is false.
      data().Empty = false;
    }

    // C++1z [dcl.init.agg]p1:
    //   An aggregate is a class with [...] no private or protected base classes
    if (Base->getAccessSpecifier() != AS_public)
      data().Aggregate = false;

    // C++ [class.virtual]p1:
    //   A class that declares or inherits a virtual function is called a
    //   polymorphic class.
    if (BaseClassDecl->isPolymorphic()) {
      data().Polymorphic = true;

      //   An aggregate is a class with [...] no virtual functions.
      data().Aggregate = false;
    }

    // C++0x [class]p7:
    //   A standard-layout class is a class that: [...]
    //    -- has no non-standard-layout base classes
    if (!BaseClassDecl->isStandardLayout())
      data().IsStandardLayout = false;
    if (!BaseClassDecl->isCXX11StandardLayout())
      data().IsCXX11StandardLayout = false;

    // Record if this base is the first non-literal field or base.
    if (!hasNonLiteralTypeFieldsOrBases() && !BaseType->isLiteralType(C))
      data().HasNonLiteralTypeFieldsOrBases = true;

    // Now go through all virtual bases of this base and add them.
    for (const auto &VBase : BaseClassDecl->vbases()) {
      // Add this base if it's not already in the list.
      if (SeenVBaseTypes.insert(C.getCanonicalType(VBase.getType())).second) {
        VBases.push_back(&VBase);

        // C++11 [class.copy]p8:
        //   The implicitly-declared copy constructor for a class X will have
        //   the form 'X::X(const X&)' if each [...] virtual base class B of X
        //   has a copy constructor whose first parameter is of type
        //   'const B&' or 'const volatile B&' [...]
        if (CXXRecordDecl *VBaseDecl = VBase.getType()->getAsCXXRecordDecl())
          if (!VBaseDecl->hasCopyConstructorWithConstParam())
            data().ImplicitCopyConstructorCanHaveConstParamForVBase = false;

        // C++1z [dcl.init.agg]p1:
        //   An aggregate is a class with [...] no virtual base classes
        data().Aggregate = false;
      }
    }

    if (Base->isVirtual()) {
      // Add this base if it's not already in the list.
      if (SeenVBaseTypes.insert(C.getCanonicalType(BaseType)).second)
        VBases.push_back(Base);

      // C++14 [meta.unary.prop] is_empty:
      //   T is a class type, but not a union type, with ... no virtual base
      //   classes
      data().Empty = false;

      // C++1z [dcl.init.agg]p1:
      //   An aggregate is a class with [...] no virtual base classes
      data().Aggregate = false;

      // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
      //   A [default constructor, copy/move constructor, or copy/move assignment
      //   operator for a class X] is trivial [...] if:
      //    -- class X has [...] no virtual base classes
      data().HasTrivialSpecialMembers &= SMF_Destructor;
      data().HasTrivialSpecialMembersForCall &= SMF_Destructor;

      // C++0x [class]p7:
      //   A standard-layout class is a class that: [...]
      //    -- has [...] no virtual base classes
      data().IsStandardLayout = false;
      data().IsCXX11StandardLayout = false;

      // C++11 [dcl.constexpr]p4:
      //   In the definition of a constexpr constructor [...]
      //    -- the class shall not have any virtual base classes
      data().DefaultedDefaultConstructorIsConstexpr = false;

      // C++1z [class.copy]p8:
      //   The implicitly-declared copy constructor for a class X will have
      //   the form 'X::X(const X&)' if each potentially constructed subobject
      //   has a copy constructor whose first parameter is of type
      //   'const B&' or 'const volatile B&' [...]
      if (!BaseClassDecl->hasCopyConstructorWithConstParam())
        data().ImplicitCopyConstructorCanHaveConstParamForVBase = false;
    } else {
      // C++ [class.ctor]p5:
      //   A default constructor is trivial [...] if:
      //    -- all the direct base classes of its class have trivial default
      //       constructors.
      if (!BaseClassDecl->hasTrivialDefaultConstructor())
        data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;

      // C++0x [class.copy]p13:
      //   A copy/move constructor for class X is trivial if [...]
      //    [...]
      //    -- the constructor selected to copy/move each direct base class
      //       subobject is trivial, and
      if (!BaseClassDecl->hasTrivialCopyConstructor())
        data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;

      if (!BaseClassDecl->hasTrivialCopyConstructorForCall())
        data().HasTrivialSpecialMembersForCall &= ~SMF_CopyConstructor;

      // If the base class doesn't have a simple move constructor, we'll eagerly
      // declare it and perform overload resolution to determine which function
      // it actually calls. If it does have a simple move constructor, this
      // check is correct.
      if (!BaseClassDecl->hasTrivialMoveConstructor())
        data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;

      if (!BaseClassDecl->hasTrivialMoveConstructorForCall())
        data().HasTrivialSpecialMembersForCall &= ~SMF_MoveConstructor;

      // C++0x [class.copy]p27:
      //   A copy/move assignment operator for class X is trivial if [...]
      //    [...]
      //    -- the assignment operator selected to copy/move each direct base
      //       class subobject is trivial, and
      if (!BaseClassDecl->hasTrivialCopyAssignment())
        data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment;
      // If the base class doesn't have a simple move assignment, we'll eagerly
      // declare it and perform overload resolution to determine which function
      // it actually calls. If it does have a simple move assignment, this
      // check is correct.
      if (!BaseClassDecl->hasTrivialMoveAssignment())
        data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment;

      // C++11 [class.ctor]p6:
      //   If that user-written default constructor would satisfy the
      //   requirements of a constexpr constructor, the implicitly-defined
      //   default constructor is constexpr.
      if (!BaseClassDecl->hasConstexprDefaultConstructor())
        data().DefaultedDefaultConstructorIsConstexpr = false;

      // C++1z [class.copy]p8:
      //   The implicitly-declared copy constructor for a class X will have
      //   the form 'X::X(const X&)' if each potentially constructed subobject
      //   has a copy constructor whose first parameter is of type
      //   'const B&' or 'const volatile B&' [...]
      if (!BaseClassDecl->hasCopyConstructorWithConstParam())
        data().ImplicitCopyConstructorCanHaveConstParamForNonVBase = false;
    }

    // C++ [class.ctor]p3:
    //   A destructor is trivial if all the direct base classes of its class
    //   have trivial destructors.
    if (!BaseClassDecl->hasTrivialDestructor())
      data().HasTrivialSpecialMembers &= ~SMF_Destructor;

    if (!BaseClassDecl->hasTrivialDestructorForCall())
      data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;

    if (!BaseClassDecl->hasIrrelevantDestructor())
      data().HasIrrelevantDestructor = false;

    // C++11 [class.copy]p18:
    //   The implicitly-declared copy assignment oeprator for a class X will
    //   have the form 'X& X::operator=(const X&)' if each direct base class B
    //   of X has a copy assignment operator whose parameter is of type 'const
    //   B&', 'const volatile B&', or 'B' [...]
    if (!BaseClassDecl->hasCopyAssignmentWithConstParam())
      data().ImplicitCopyAssignmentHasConstParam = false;

    // A class has an Objective-C object member if... or any of its bases
    // has an Objective-C object member.
    if (BaseClassDecl->hasObjectMember())
      setHasObjectMember(true);

    if (BaseClassDecl->hasVolatileMember())
      setHasVolatileMember(true);

    if (BaseClassDecl->getArgPassingRestrictions() ==
        RecordDecl::APK_CanNeverPassInRegs)
      setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);

    // Keep track of the presence of mutable fields.
    if (BaseClassDecl->hasMutableFields()) {
      data().HasMutableFields = true;
      data().NeedOverloadResolutionForCopyConstructor = true;
    }

    if (BaseClassDecl->hasUninitializedReferenceMember())
      data().HasUninitializedReferenceMember = true;

    if (!BaseClassDecl->allowConstDefaultInit())
      data().HasUninitializedFields = true;

    addedClassSubobject(BaseClassDecl);
  }

  // C++2a [class]p7:
  //   A class S is a standard-layout class if it:
  //     -- has at most one base class subobject of any given type
  //
  // Note that we only need to check this for classes with more than one base
  // class. If there's only one base class, and it's standard layout, then
  // we know there are no repeated base classes.
  if (data().IsStandardLayout && NumBases > 1 && hasRepeatedBaseClass(this))
    data().IsStandardLayout = false;

  if (VBases.empty()) {
    data().IsParsingBaseSpecifiers = false;
    return;
  }

  // Create base specifier for any direct or indirect virtual bases.
  data().VBases = new (C) CXXBaseSpecifier[VBases.size()];
  data().NumVBases = VBases.size();
  for (int I = 0, E = VBases.size(); I != E; ++I) {
    QualType Type = VBases[I]->getType();
    if (!Type->isDependentType())
      addedClassSubobject(Type->getAsCXXRecordDecl());
    data().getVBases()[I] = *VBases[I];
  }

  data().IsParsingBaseSpecifiers = false;
}

unsigned CXXRecordDecl::getODRHash() const {
  assert(hasDefinition() && "ODRHash only for records with definitions");

  // Previously calculated hash is stored in DefinitionData.
  if (DefinitionData->HasODRHash)
    return DefinitionData->ODRHash;

  // Only calculate hash on first call of getODRHash per record.
  ODRHash Hash;
  Hash.AddCXXRecordDecl(getDefinition());
  DefinitionData->HasODRHash = true;
  DefinitionData->ODRHash = Hash.CalculateHash();

  return DefinitionData->ODRHash;
}

void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
  // C++11 [class.copy]p11:
  //   A defaulted copy/move constructor for a class X is defined as
  //   deleted if X has:
  //    -- a direct or virtual base class B that cannot be copied/moved [...]
  //    -- a non-static data member of class type M (or array thereof)
  //       that cannot be copied or moved [...]
  if (!Subobj->hasSimpleCopyConstructor())
    data().NeedOverloadResolutionForCopyConstructor = true;
  if (!Subobj->hasSimpleMoveConstructor())
    data().NeedOverloadResolutionForMoveConstructor = true;

  // C++11 [class.copy]p23:
  //   A defaulted copy/move assignment operator for a class X is defined as
  //   deleted if X has:
  //    -- a direct or virtual base class B that cannot be copied/moved [...]
  //    -- a non-static data member of class type M (or array thereof)
  //        that cannot be copied or moved [...]
  if (!Subobj->hasSimpleMoveAssignment())
    data().NeedOverloadResolutionForMoveAssignment = true;

  // C++11 [class.ctor]p5, C++11 [class.copy]p11, C++11 [class.dtor]p5:
  //   A defaulted [ctor or dtor] for a class X is defined as
  //   deleted if X has:
  //    -- any direct or virtual base class [...] has a type with a destructor
  //       that is deleted or inaccessible from the defaulted [ctor or dtor].
  //    -- any non-static data member has a type with a destructor
  //       that is deleted or inaccessible from the defaulted [ctor or dtor].
  if (!Subobj->hasSimpleDestructor()) {
    data().NeedOverloadResolutionForCopyConstructor = true;
    data().NeedOverloadResolutionForMoveConstructor = true;
    data().NeedOverloadResolutionForDestructor = true;
  }
}

bool CXXRecordDecl::hasAnyDependentBases() const {
  if (!isDependentContext())
    return false;

  return !forallBases([](const CXXRecordDecl *) { return true; });
}

bool CXXRecordDecl::isTriviallyCopyable() const {
  // C++0x [class]p5:
  //   A trivially copyable class is a class that:
  //   -- has no non-trivial copy constructors,
  if (hasNonTrivialCopyConstructor()) return false;
  //   -- has no non-trivial move constructors,
  if (hasNonTrivialMoveConstructor()) return false;
  //   -- has no non-trivial copy assignment operators,
  if (hasNonTrivialCopyAssignment()) return false;
  //   -- has no non-trivial move assignment operators, and
  if (hasNonTrivialMoveAssignment()) return false;
  //   -- has a trivial destructor.
  if (!hasTrivialDestructor()) return false;

  return true;
}

void CXXRecordDecl::markedVirtualFunctionPure() {
  // C++ [class.abstract]p2:
  //   A class is abstract if it has at least one pure virtual function.
  data().Abstract = true;
}

bool CXXRecordDecl::hasSubobjectAtOffsetZeroOfEmptyBaseType(
    ASTContext &Ctx, const CXXRecordDecl *XFirst) {
  if (!getNumBases())
    return false;

  llvm::SmallPtrSet<const CXXRecordDecl*, 8> Bases;
  llvm::SmallPtrSet<const CXXRecordDecl*, 8> M;
  SmallVector<const CXXRecordDecl*, 8> WorkList;

  // Visit a type that we have determined is an element of M(S).
  auto Visit = [&](const CXXRecordDecl *RD) -> bool {
    RD = RD->getCanonicalDecl();

    // C++2a [class]p8:
    //   A class S is a standard-layout class if it [...] has no element of the
    //   set M(S) of types as a base class.
    //
    // If we find a subobject of an empty type, it might also be a base class,
    // so we'll need to walk the base classes to check.
    if (!RD->data().HasBasesWithFields) {
      // Walk the bases the first time, stopping if we find the type. Build a
      // set of them so we don't need to walk them again.
      if (Bases.empty()) {
        bool RDIsBase = !forallBases([&](const CXXRecordDecl *Base) -> bool {
          Base = Base->getCanonicalDecl();
          if (RD == Base)
            return false;
          Bases.insert(Base);
          return true;
        });
        if (RDIsBase)
          return true;
      } else {
        if (Bases.count(RD))
          return true;
      }
    }

    if (M.insert(RD).second)
      WorkList.push_back(RD);
    return false;
  };

  if (Visit(XFirst))
    return true;

  while (!WorkList.empty()) {
    const CXXRecordDecl *X = WorkList.pop_back_val();

    // FIXME: We don't check the bases of X. That matches the standard, but
    // that sure looks like a wording bug.

    //   -- If X is a non-union class type with a non-static data member
    //      [recurse to] the first non-static data member of X
    //   -- If X is a union type, [recurse to union members]
    for (auto *FD : X->fields()) {
      // FIXME: Should we really care about the type of the first non-static
      // data member of a non-union if there are preceding unnamed bit-fields?
      if (FD->isUnnamedBitfield())
        continue;

      //   -- If X is n array type, [visit the element type]
      QualType T = Ctx.getBaseElementType(FD->getType());
      if (auto *RD = T->getAsCXXRecordDecl())
        if (Visit(RD))
          return true;

      if (!X->isUnion())
        break;
    }
  }

  return false;
}

void CXXRecordDecl::addedMember(Decl *D) {
  if (!D->isImplicit() &&
      !isa<FieldDecl>(D) &&
      !isa<IndirectFieldDecl>(D) &&
      (!isa<TagDecl>(D) || cast<TagDecl>(D)->getTagKind() == TTK_Class ||
        cast<TagDecl>(D)->getTagKind() == TTK_Interface))
    data().HasOnlyCMembers = false;

  // Ignore friends and invalid declarations.
  if (D->getFriendObjectKind() || D->isInvalidDecl())
    return;

  auto *FunTmpl = dyn_cast<FunctionTemplateDecl>(D);
  if (FunTmpl)
    D = FunTmpl->getTemplatedDecl();

  // FIXME: Pass NamedDecl* to addedMember?
  Decl *DUnderlying = D;
  if (auto *ND = dyn_cast<NamedDecl>(DUnderlying)) {
    DUnderlying = ND->getUnderlyingDecl();
    if (auto *UnderlyingFunTmpl = dyn_cast<FunctionTemplateDecl>(DUnderlying))
      DUnderlying = UnderlyingFunTmpl->getTemplatedDecl();
  }

  if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
    if (Method->isVirtual()) {
      // C++ [dcl.init.aggr]p1:
      //   An aggregate is an array or a class with [...] no virtual functions.
      data().Aggregate = false;

      // C++ [class]p4:
      //   A POD-struct is an aggregate class...
      data().PlainOldData = false;

      // C++14 [meta.unary.prop]p4:
      //   T is a class type [...] with [...] no virtual member functions...
      data().Empty = false;

      // C++ [class.virtual]p1:
      //   A class that declares or inherits a virtual function is called a
      //   polymorphic class.
      data().Polymorphic = true;

      // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
      //   A [default constructor, copy/move constructor, or copy/move
      //   assignment operator for a class X] is trivial [...] if:
      //    -- class X has no virtual functions [...]
      data().HasTrivialSpecialMembers &= SMF_Destructor;
      data().HasTrivialSpecialMembersForCall &= SMF_Destructor;

      // C++0x [class]p7:
      //   A standard-layout class is a class that: [...]
      //    -- has no virtual functions
      data().IsStandardLayout = false;
      data().IsCXX11StandardLayout = false;
    }
  }

  // Notify the listener if an implicit member was added after the definition
  // was completed.
  if (!isBeingDefined() && D->isImplicit())
    if (ASTMutationListener *L = getASTMutationListener())
      L->AddedCXXImplicitMember(data().Definition, D);

  // The kind of special member this declaration is, if any.
  unsigned SMKind = 0;

  // Handle constructors.
  if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
    if (!Constructor->isImplicit()) {
      // Note that we have a user-declared constructor.
      data().UserDeclaredConstructor = true;

      // C++ [class]p4:
      //   A POD-struct is an aggregate class [...]
      // Since the POD bit is meant to be C++03 POD-ness, clear it even if the
      // type is technically an aggregate in C++0x since it wouldn't be in 03.
      data().PlainOldData = false;
    }

    if (Constructor->isDefaultConstructor()) {
      SMKind |= SMF_DefaultConstructor;

      if (Constructor->isUserProvided())
        data().UserProvidedDefaultConstructor = true;
      if (Constructor->isConstexpr())
        data().HasConstexprDefaultConstructor = true;
      if (Constructor->isDefaulted())
        data().HasDefaultedDefaultConstructor = true;
    }

    if (!FunTmpl) {
      unsigned Quals;
      if (Constructor->isCopyConstructor(Quals)) {
        SMKind |= SMF_CopyConstructor;

        if (Quals & Qualifiers::Const)
          data().HasDeclaredCopyConstructorWithConstParam = true;
      } else if (Constructor->isMoveConstructor())
        SMKind |= SMF_MoveConstructor;
    }

    // C++11 [dcl.init.aggr]p1: DR1518
    //   An aggregate is an array or a class with no user-provided, explicit, or
    //   inherited constructors
    if (Constructor->isUserProvided() || Constructor->isExplicit())
      data().Aggregate = false;
  }

  // Handle constructors, including those inherited from base classes.
  if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(DUnderlying)) {
    // Record if we see any constexpr constructors which are neither copy
    // nor move constructors.
    // C++1z [basic.types]p10:
    //   [...] has at least one constexpr constructor or constructor template
    //   (possibly inherited from a base class) that is not a copy or move
    //   constructor [...]
    if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor())
      data().HasConstexprNonCopyMoveConstructor = true;
  }

  // Handle destructors.
  if (const auto *DD = dyn_cast<CXXDestructorDecl>(D)) {
    SMKind |= SMF_Destructor;

    if (DD->isUserProvided())
      data().HasIrrelevantDestructor = false;
    // If the destructor is explicitly defaulted and not trivial or not public
    // or if the destructor is deleted, we clear HasIrrelevantDestructor in
    // finishedDefaultedOrDeletedMember.

    // C++11 [class.dtor]p5:
    //   A destructor is trivial if [...] the destructor is not virtual.
    if (DD->isVirtual()) {
      data().HasTrivialSpecialMembers &= ~SMF_Destructor;
      data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
    }
  }

  // Handle member functions.
  if (const auto *Method = dyn_cast<CXXMethodDecl>(D)) {
    if (Method->isCopyAssignmentOperator()) {
      SMKind |= SMF_CopyAssignment;

      const auto *ParamTy =
          Method->getParamDecl(0)->getType()->getAs<ReferenceType>();
      if (!ParamTy || ParamTy->getPointeeType().isConstQualified())
        data().HasDeclaredCopyAssignmentWithConstParam = true;
    }

    if (Method->isMoveAssignmentOperator())
      SMKind |= SMF_MoveAssignment;

    // Keep the list of conversion functions up-to-date.
    if (auto *Conversion = dyn_cast<CXXConversionDecl>(D)) {
      // FIXME: We use the 'unsafe' accessor for the access specifier here,
      // because Sema may not have set it yet. That's really just a misdesign
      // in Sema. However, LLDB *will* have set the access specifier correctly,
      // and adds declarations after the class is technically completed,
      // so completeDefinition()'s overriding of the access specifiers doesn't
      // work.
      AccessSpecifier AS = Conversion->getAccessUnsafe();

      if (Conversion->getPrimaryTemplate()) {
        // We don't record specializations.
      } else {
        ASTContext &Ctx = getASTContext();
        ASTUnresolvedSet &Conversions = data().Conversions.get(Ctx);
        NamedDecl *Primary =
            FunTmpl ? cast<NamedDecl>(FunTmpl) : cast<NamedDecl>(Conversion);
        if (Primary->getPreviousDecl())
          Conversions.replace(cast<NamedDecl>(Primary->getPreviousDecl()),
                              Primary, AS);
        else
          Conversions.addDecl(Ctx, Primary, AS);
      }
    }

    if (SMKind) {
      // If this is the first declaration of a special member, we no longer have
      // an implicit trivial special member.
      data().HasTrivialSpecialMembers &=
          data().DeclaredSpecialMembers | ~SMKind;
      data().HasTrivialSpecialMembersForCall &=
          data().DeclaredSpecialMembers | ~SMKind;

      if (!Method->isImplicit() && !Method->isUserProvided()) {
        // This method is user-declared but not user-provided. We can't work out
        // whether it's trivial yet (not until we get to the end of the class).
        // We'll handle this method in finishedDefaultedOrDeletedMember.
      } else if (Method->isTrivial()) {
        data().HasTrivialSpecialMembers |= SMKind;
        data().HasTrivialSpecialMembersForCall |= SMKind;
      } else if (Method->isTrivialForCall()) {
        data().HasTrivialSpecialMembersForCall |= SMKind;
        data().DeclaredNonTrivialSpecialMembers |= SMKind;
      } else {
        data().DeclaredNonTrivialSpecialMembers |= SMKind;
        // If this is a user-provided function, do not set
        // DeclaredNonTrivialSpecialMembersForCall here since we don't know
        // yet whether the method would be considered non-trivial for the
        // purpose of calls (attribute "trivial_abi" can be dropped from the
        // class later, which can change the special method's triviality).
        if (!Method->isUserProvided())
          data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
      }

      // Note when we have declared a declared special member, and suppress the
      // implicit declaration of this special member.
      data().DeclaredSpecialMembers |= SMKind;

      if (!Method->isImplicit()) {
        data().UserDeclaredSpecialMembers |= SMKind;

        // C++03 [class]p4:
        //   A POD-struct is an aggregate class that has [...] no user-defined
        //   copy assignment operator and no user-defined destructor.
        //
        // Since the POD bit is meant to be C++03 POD-ness, and in C++03,
        // aggregates could not have any constructors, clear it even for an
        // explicitly defaulted or deleted constructor.
        // type is technically an aggregate in C++0x since it wouldn't be in 03.
        //
        // Also, a user-declared move assignment operator makes a class non-POD.
        // This is an extension in C++03.
        data().PlainOldData = false;
      }
    }

    return;
  }

  // Handle non-static data members.
  if (const auto *Field = dyn_cast<FieldDecl>(D)) {
    ASTContext &Context = getASTContext();

    // C++2a [class]p7:
    //   A standard-layout class is a class that:
    //    [...]
    //    -- has all non-static data members and bit-fields in the class and
    //       its base classes first declared in the same class
    if (data().HasBasesWithFields)
      data().IsStandardLayout = false;

    // C++ [class.bit]p2:
    //   A declaration for a bit-field that omits the identifier declares an
    //   unnamed bit-field. Unnamed bit-fields are not members and cannot be
    //   initialized.
    if (Field->isUnnamedBitfield()) {
      // C++ [meta.unary.prop]p4: [LWG2358]
      //   T is a class type [...] with [...] no unnamed bit-fields of non-zero
      //   length
      if (data().Empty && !Field->isZeroLengthBitField(Context) &&
          Context.getLangOpts().getClangABICompat() >
              LangOptions::ClangABI::Ver6)
        data().Empty = false;
      return;
    }

    // C++11 [class]p7:
    //   A standard-layout class is a class that:
    //    -- either has no non-static data members in the most derived class
    //       [...] or has no base classes with non-static data members
    if (data().HasBasesWithNonStaticDataMembers)
      data().IsCXX11StandardLayout = false;

    // C++ [dcl.init.aggr]p1:
    //   An aggregate is an array or a class (clause 9) with [...] no
    //   private or protected non-static data members (clause 11).
    //
    // A POD must be an aggregate.
    if (D->getAccess() == AS_private || D->getAccess() == AS_protected) {
      data().Aggregate = false;
      data().PlainOldData = false;
    }

    // Track whether this is the first field. We use this when checking
    // whether the class is standard-layout below.
    bool IsFirstField = !data().HasPrivateFields &&
                        !data().HasProtectedFields && !data().HasPublicFields;

    // C++0x [class]p7:
    //   A standard-layout class is a class that:
    //    [...]
    //    -- has the same access control for all non-static data members,
    switch (D->getAccess()) {
    case AS_private:    data().HasPrivateFields = true;   break;
    case AS_protected:  data().HasProtectedFields = true; break;
    case AS_public:     data().HasPublicFields = true;    break;
    case AS_none:       llvm_unreachable("Invalid access specifier");
    };
    if ((data().HasPrivateFields + data().HasProtectedFields +
         data().HasPublicFields) > 1) {
      data().IsStandardLayout = false;
      data().IsCXX11StandardLayout = false;
    }

    // Keep track of the presence of mutable fields.
    if (Field->isMutable()) {
      data().HasMutableFields = true;
      data().NeedOverloadResolutionForCopyConstructor = true;
    }

    // C++11 [class.union]p8, DR1460:
    //   If X is a union, a non-static data member of X that is not an anonymous
    //   union is a variant member of X.
    if (isUnion() && !Field->isAnonymousStructOrUnion())
      data().HasVariantMembers = true;

    // C++0x [class]p9:
    //   A POD struct is a class that is both a trivial class and a
    //   standard-layout class, and has no non-static data members of type
    //   non-POD struct, non-POD union (or array of such types).
    //
    // Automatic Reference Counting: the presence of a member of Objective-C pointer type
    // that does not explicitly have no lifetime makes the class a non-POD.
    QualType T = Context.getBaseElementType(Field->getType());
    if (T->isObjCRetainableType() || T.isObjCGCStrong()) {
      if (T.hasNonTrivialObjCLifetime()) {
        // Objective-C Automatic Reference Counting:
        //   If a class has a non-static data member of Objective-C pointer
        //   type (or array thereof), it is a non-POD type and its
        //   default constructor (if any), copy constructor, move constructor,
        //   copy assignment operator, move assignment operator, and destructor are
        //   non-trivial.
        setHasObjectMember(true);
        struct DefinitionData &Data = data();
        Data.PlainOldData = false;
        Data.HasTrivialSpecialMembers = 0;

        // __strong or __weak fields do not make special functions non-trivial
        // for the purpose of calls.
        Qualifiers::ObjCLifetime LT = T.getQualifiers().getObjCLifetime();
        if (LT != Qualifiers::OCL_Strong && LT != Qualifiers::OCL_Weak)
          data().HasTrivialSpecialMembersForCall = 0;

        // Structs with __weak fields should never be passed directly.
        if (LT == Qualifiers::OCL_Weak)
          setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);

        Data.HasIrrelevantDestructor = false;
      } else if (!Context.getLangOpts().ObjCAutoRefCount) {
        setHasObjectMember(true);
      }
    } else if (!T.isCXX98PODType(Context))
      data().PlainOldData = false;

    if (T->isReferenceType()) {
      if (!Field->hasInClassInitializer())
        data().HasUninitializedReferenceMember = true;

      // C++0x [class]p7:
      //   A standard-layout class is a class that:
      //    -- has no non-static data members of type [...] reference,
      data().IsStandardLayout = false;
      data().IsCXX11StandardLayout = false;

      // C++1z [class.copy.ctor]p10:
      //   A defaulted copy constructor for a class X is defined as deleted if X has:
      //    -- a non-static data member of rvalue reference type
      if (T->isRValueReferenceType())
        data().DefaultedCopyConstructorIsDeleted = true;
    }

    if (!Field->hasInClassInitializer() && !Field->isMutable()) {
      if (CXXRecordDecl *FieldType = T->getAsCXXRecordDecl()) {
        if (FieldType->hasDefinition() && !FieldType->allowConstDefaultInit())
          data().HasUninitializedFields = true;
      } else {
        data().HasUninitializedFields = true;
      }
    }

    // Record if this field is the first non-literal or volatile field or base.
    if (!T->isLiteralType(Context) || T.isVolatileQualified())
      data().HasNonLiteralTypeFieldsOrBases = true;

    if (Field->hasInClassInitializer() ||
        (Field->isAnonymousStructOrUnion() &&
         Field->getType()->getAsCXXRecordDecl()->hasInClassInitializer())) {
      data().HasInClassInitializer = true;

      // C++11 [class]p5:
      //   A default constructor is trivial if [...] no non-static data member
      //   of its class has a brace-or-equal-initializer.
      data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;

      // C++11 [dcl.init.aggr]p1:
      //   An aggregate is a [...] class with [...] no
      //   brace-or-equal-initializers for non-static data members.
      //
      // This rule was removed in C++14.
      if (!getASTContext().getLangOpts().CPlusPlus14)
        data().Aggregate = false;

      // C++11 [class]p10:
      //   A POD struct is [...] a trivial class.
      data().PlainOldData = false;
    }

    // C++11 [class.copy]p23:
    //   A defaulted copy/move assignment operator for a class X is defined
    //   as deleted if X has:
    //    -- a non-static data member of reference type
    if (T->isReferenceType())
      data().DefaultedMoveAssignmentIsDeleted = true;

    if (const auto *RecordTy = T->getAs<RecordType>()) {
      auto *FieldRec = cast<CXXRecordDecl>(RecordTy->getDecl());
      if (FieldRec->getDefinition()) {
        addedClassSubobject(FieldRec);

        // We may need to perform overload resolution to determine whether a
        // field can be moved if it's const or volatile qualified.
        if (T.getCVRQualifiers() & (Qualifiers::Const | Qualifiers::Volatile)) {
          // We need to care about 'const' for the copy constructor because an
          // implicit copy constructor might be declared with a non-const
          // parameter.
          data().NeedOverloadResolutionForCopyConstructor = true;
          data().NeedOverloadResolutionForMoveConstructor = true;
          data().NeedOverloadResolutionForMoveAssignment = true;
        }

        // C++11 [class.ctor]p5, C++11 [class.copy]p11:
        //   A defaulted [special member] for a class X is defined as
        //   deleted if:
        //    -- X is a union-like class that has a variant member with a
        //       non-trivial [corresponding special member]
        if (isUnion()) {
          if (FieldRec->hasNonTrivialCopyConstructor())
            data().DefaultedCopyConstructorIsDeleted = true;
          if (FieldRec->hasNonTrivialMoveConstructor())
            data().DefaultedMoveConstructorIsDeleted = true;
          if (FieldRec->hasNonTrivialMoveAssignment())
            data().DefaultedMoveAssignmentIsDeleted = true;
          if (FieldRec->hasNonTrivialDestructor())
            data().DefaultedDestructorIsDeleted = true;
        }

        // For an anonymous union member, our overload resolution will perform
        // overload resolution for its members.
        if (Field->isAnonymousStructOrUnion()) {
          data().NeedOverloadResolutionForCopyConstructor |=
              FieldRec->data().NeedOverloadResolutionForCopyConstructor;
          data().NeedOverloadResolutionForMoveConstructor |=
              FieldRec->data().NeedOverloadResolutionForMoveConstructor;
          data().NeedOverloadResolutionForMoveAssignment |=
              FieldRec->data().NeedOverloadResolutionForMoveAssignment;
          data().NeedOverloadResolutionForDestructor |=
              FieldRec->data().NeedOverloadResolutionForDestructor;
        }

        // C++0x [class.ctor]p5:
        //   A default constructor is trivial [...] if:
        //    -- for all the non-static data members of its class that are of
        //       class type (or array thereof), each such class has a trivial
        //       default constructor.
        if (!FieldRec->hasTrivialDefaultConstructor())
          data().HasTrivialSpecialMembers &= ~SMF_DefaultConstructor;

        // C++0x [class.copy]p13:
        //   A copy/move constructor for class X is trivial if [...]
        //    [...]
        //    -- for each non-static data member of X that is of class type (or
        //       an array thereof), the constructor selected to copy/move that
        //       member is trivial;
        if (!FieldRec->hasTrivialCopyConstructor())
          data().HasTrivialSpecialMembers &= ~SMF_CopyConstructor;

        if (!FieldRec->hasTrivialCopyConstructorForCall())
          data().HasTrivialSpecialMembersForCall &= ~SMF_CopyConstructor;

        // If the field doesn't have a simple move constructor, we'll eagerly
        // declare the move constructor for this class and we'll decide whether
        // it's trivial then.
        if (!FieldRec->hasTrivialMoveConstructor())
          data().HasTrivialSpecialMembers &= ~SMF_MoveConstructor;

        if (!FieldRec->hasTrivialMoveConstructorForCall())
          data().HasTrivialSpecialMembersForCall &= ~SMF_MoveConstructor;

        // C++0x [class.copy]p27:
        //   A copy/move assignment operator for class X is trivial if [...]
        //    [...]
        //    -- for each non-static data member of X that is of class type (or
        //       an array thereof), the assignment operator selected to
        //       copy/move that member is trivial;
        if (!FieldRec->hasTrivialCopyAssignment())
          data().HasTrivialSpecialMembers &= ~SMF_CopyAssignment;
        // If the field doesn't have a simple move assignment, we'll eagerly
        // declare the move assignment for this class and we'll decide whether
        // it's trivial then.
        if (!FieldRec->hasTrivialMoveAssignment())
          data().HasTrivialSpecialMembers &= ~SMF_MoveAssignment;

        if (!FieldRec->hasTrivialDestructor())
          data().HasTrivialSpecialMembers &= ~SMF_Destructor;
        if (!FieldRec->hasTrivialDestructorForCall())
          data().HasTrivialSpecialMembersForCall &= ~SMF_Destructor;
        if (!FieldRec->hasIrrelevantDestructor())
          data().HasIrrelevantDestructor = false;
        if (FieldRec->hasObjectMember())
          setHasObjectMember(true);
        if (FieldRec->hasVolatileMember())
          setHasVolatileMember(true);
        if (FieldRec->getArgPassingRestrictions() ==
            RecordDecl::APK_CanNeverPassInRegs)
          setArgPassingRestrictions(RecordDecl::APK_CanNeverPassInRegs);

        // C++0x [class]p7:
        //   A standard-layout class is a class that:
        //    -- has no non-static data members of type non-standard-layout
        //       class (or array of such types) [...]
        if (!FieldRec->isStandardLayout())
          data().IsStandardLayout = false;
        if (!FieldRec->isCXX11StandardLayout())
          data().IsCXX11StandardLayout = false;

        // C++2a [class]p7:
        //   A standard-layout class is a class that:
        //    [...]
        //    -- has no element of the set M(S) of types as a base class.
        if (data().IsStandardLayout && (isUnion() || IsFirstField) &&
            hasSubobjectAtOffsetZeroOfEmptyBaseType(Context, FieldRec))
          data().IsStandardLayout = false;

        // C++11 [class]p7:
        //   A standard-layout class is a class that:
        //    -- has no base classes of the same type as the first non-static
        //       data member
        if (data().IsCXX11StandardLayout && IsFirstField) {
          // FIXME: We should check all base classes here, not just direct
          // base classes.
          for (const auto &BI : bases()) {
            if (Context.hasSameUnqualifiedType(BI.getType(), T)) {
              data().IsCXX11StandardLayout = false;
              break;
            }
          }
        }

        // Keep track of the presence of mutable fields.
        if (FieldRec->hasMutableFields()) {
          data().HasMutableFields = true;
          data().NeedOverloadResolutionForCopyConstructor = true;
        }

        // C++11 [class.copy]p13:
        //   If the implicitly-defined constructor would satisfy the
        //   requirements of a constexpr constructor, the implicitly-defined
        //   constructor is constexpr.
        // C++11 [dcl.constexpr]p4:
        //    -- every constructor involved in initializing non-static data
        //       members [...] shall be a constexpr constructor
        if (!Field->hasInClassInitializer() &&
            !FieldRec->hasConstexprDefaultConstructor() && !isUnion())
          // The standard requires any in-class initializer to be a constant
          // expression. We consider this to be a defect.
          data().DefaultedDefaultConstructorIsConstexpr = false;

        // C++11 [class.copy]p8:
        //   The implicitly-declared copy constructor for a class X will have
        //   the form 'X::X(const X&)' if each potentially constructed subobject
        //   of a class type M (or array thereof) has a copy constructor whose
        //   first parameter is of type 'const M&' or 'const volatile M&'.
        if (!FieldRec->hasCopyConstructorWithConstParam())
          data().ImplicitCopyConstructorCanHaveConstParamForNonVBase = false;

        // C++11 [class.copy]p18:
        //   The implicitly-declared copy assignment oeprator for a class X will
        //   have the form 'X& X::operator=(const X&)' if [...] for all the
        //   non-static data members of X that are of a class type M (or array
        //   thereof), each such class type has a copy assignment operator whose
        //   parameter is of type 'const M&', 'const volatile M&' or 'M'.
        if (!FieldRec->hasCopyAssignmentWithConstParam())
          data().ImplicitCopyAssignmentHasConstParam = false;

        if (FieldRec->hasUninitializedReferenceMember() &&
            !Field->hasInClassInitializer())
          data().HasUninitializedReferenceMember = true;

        // C++11 [class.union]p8, DR1460:
        //   a non-static data member of an anonymous union that is a member of
        //   X is also a variant member of X.
        if (FieldRec->hasVariantMembers() &&
            Field->isAnonymousStructOrUnion())
          data().HasVariantMembers = true;
      }
    } else {
      // Base element type of field is a non-class type.
      if (!T->isLiteralType(Context) ||
          (!Field->hasInClassInitializer() && !isUnion()))
        data().DefaultedDefaultConstructorIsConstexpr = false;

      // C++11 [class.copy]p23:
      //   A defaulted copy/move assignment operator for a class X is defined
      //   as deleted if X has:
      //    -- a non-static data member of const non-class type (or array
      //       thereof)
      if (T.isConstQualified())
        data().DefaultedMoveAssignmentIsDeleted = true;
    }

    // C++14 [meta.unary.prop]p4:
    //   T is a class type [...] with [...] no non-static data members
    data().Empty = false;
  }

  // Handle using declarations of conversion functions.
  if (auto *Shadow = dyn_cast<UsingShadowDecl>(D)) {
    if (Shadow->getDeclName().getNameKind()
          == DeclarationName::CXXConversionFunctionName) {
      ASTContext &Ctx = getASTContext();
      data().Conversions.get(Ctx).addDecl(Ctx, Shadow, Shadow->getAccess());
    }
  }

  if (const auto *Using = dyn_cast<UsingDecl>(D)) {
    if (Using->getDeclName().getNameKind() ==
        DeclarationName::CXXConstructorName) {
      data().HasInheritedConstructor = true;
      // C++1z [dcl.init.aggr]p1:
      //  An aggregate is [...] a class [...] with no inherited constructors
      data().Aggregate = false;
    }

    if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal)
      data().HasInheritedAssignment = true;
  }
}

void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) {
  assert(!D->isImplicit() && !D->isUserProvided());

  // The kind of special member this declaration is, if any.
  unsigned SMKind = 0;

  if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
    if (Constructor->isDefaultConstructor()) {
      SMKind |= SMF_DefaultConstructor;
      if (Constructor->isConstexpr())
        data().HasConstexprDefaultConstructor = true;
    }
    if (Constructor->isCopyConstructor())
      SMKind |= SMF_CopyConstructor;
    else if (Constructor->isMoveConstructor())
      SMKind |= SMF_MoveConstructor;
    else if (Constructor->isConstexpr())
      // We may now know that the constructor is constexpr.
      data().HasConstexprNonCopyMoveConstructor = true;
  } else if (isa<CXXDestructorDecl>(D)) {
    SMKind |= SMF_Destructor;
    if (!D->isTrivial() || D->getAccess() != AS_public || D->isDeleted())
      data().HasIrrelevantDestructor = false;
  } else if (D->isCopyAssignmentOperator())
    SMKind |= SMF_CopyAssignment;
  else if (D->isMoveAssignmentOperator())
    SMKind |= SMF_MoveAssignment;

  // Update which trivial / non-trivial special members we have.
  // addedMember will have skipped this step for this member.
  if (D->isTrivial())
    data().HasTrivialSpecialMembers |= SMKind;
  else
    data().DeclaredNonTrivialSpecialMembers |= SMKind;
}

void CXXRecordDecl::setTrivialForCallFlags(CXXMethodDecl *D) {
  unsigned SMKind = 0;

  if (const auto *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
    if (Constructor->isCopyConstructor())
      SMKind = SMF_CopyConstructor;
    else if (Constructor->isMoveConstructor())
      SMKind = SMF_MoveConstructor;
  } else if (isa<CXXDestructorDecl>(D))
    SMKind = SMF_Destructor;

  if (D->isTrivialForCall())
    data().HasTrivialSpecialMembersForCall |= SMKind;
  else
    data().DeclaredNonTrivialSpecialMembersForCall |= SMKind;
}

bool CXXRecordDecl::isCLike() const {
  if (getTagKind() == TTK_Class || getTagKind() == TTK_Interface ||
      !TemplateOrInstantiation.isNull())
    return false;
  if (!hasDefinition())
    return true;

  return isPOD() && data().HasOnlyCMembers;
}

bool CXXRecordDecl::isGenericLambda() const {
  if (!isLambda()) return false;
  return getLambdaData().IsGenericLambda;
}

CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
  if (!isLambda()) return nullptr;
  DeclarationName Name =
    getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
  DeclContext::lookup_result Calls = lookup(Name);

  assert(!Calls.empty() && "Missing lambda call operator!");
  assert(Calls.size() == 1 && "More than one lambda call operator!");

  NamedDecl *CallOp = Calls.front();
  if (const auto *CallOpTmpl = dyn_cast<FunctionTemplateDecl>(CallOp))
    return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());

  return cast<CXXMethodDecl>(CallOp);
}

CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
  if (!isLambda()) return nullptr;
  DeclarationName Name =
    &getASTContext().Idents.get(getLambdaStaticInvokerName());
  DeclContext::lookup_result Invoker = lookup(Name);
  if (Invoker.empty()) return nullptr;
  assert(Invoker.size() == 1 && "More than one static invoker operator!");
  NamedDecl *InvokerFun = Invoker.front();
  if (const auto *InvokerTemplate = dyn_cast<FunctionTemplateDecl>(InvokerFun))
    return cast<CXXMethodDecl>(InvokerTemplate->getTemplatedDecl());

  return cast<CXXMethodDecl>(InvokerFun);
}

void CXXRecordDecl::getCaptureFields(
       llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
       FieldDecl *&ThisCapture) const {
  Captures.clear();
  ThisCapture = nullptr;

  LambdaDefinitionData &Lambda = getLambdaData();
  RecordDecl::field_iterator Field = field_begin();
  for (const LambdaCapture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures;
       C != CEnd; ++C, ++Field) {
    if (C->capturesThis())
      ThisCapture = *Field;
    else if (C->capturesVariable())
      Captures[C->getCapturedVar()] = *Field;
  }
  assert(Field == field_end());
}

TemplateParameterList *
CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
  if (!isLambda()) return nullptr;
  CXXMethodDecl *CallOp = getLambdaCallOperator();
  if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate())
    return Tmpl->getTemplateParameters();
  return nullptr;
}

Decl *CXXRecordDecl::getLambdaContextDecl() const {
  assert(isLambda() && "Not a lambda closure type!");
  ExternalASTSource *Source = getParentASTContext().getExternalSource();
  return getLambdaData().ContextDecl.get(Source);
}

static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
  QualType T =
      cast<CXXConversionDecl>(Conv->getUnderlyingDecl()->getAsFunction())
          ->getConversionType();
  return Context.getCanonicalType(T);
}

/// Collect the visible conversions of a base class.
///
/// \param Record a base class of the class we're considering
/// \param InVirtual whether this base class is a virtual base (or a base
///   of a virtual base)
/// \param Access the access along the inheritance path to this base
/// \param ParentHiddenTypes the conversions provided by the inheritors
///   of this base
/// \param Output the set to which to add conversions from non-virtual bases
/// \param VOutput the set to which to add conversions from virtual bases
/// \param HiddenVBaseCs the set of conversions which were hidden in a
///   virtual base along some inheritance path
static void CollectVisibleConversions(ASTContext &Context,
                                      CXXRecordDecl *Record,
                                      bool InVirtual,
                                      AccessSpecifier Access,
                  const llvm::SmallPtrSet<CanQualType, 8> &ParentHiddenTypes,
                                      ASTUnresolvedSet &Output,
                                      UnresolvedSetImpl &VOutput,
                           llvm::SmallPtrSet<NamedDecl*, 8> &HiddenVBaseCs) {
  // The set of types which have conversions in this class or its
  // subclasses.  As an optimization, we don't copy the derived set
  // unless it might change.
  const llvm::SmallPtrSet<CanQualType, 8> *HiddenTypes = &ParentHiddenTypes;
  llvm::SmallPtrSet<CanQualType, 8> HiddenTypesBuffer;

  // Collect the direct conversions and figure out which conversions
  // will be hidden in the subclasses.
  CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin();
  CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end();
  if (ConvI != ConvE) {
    HiddenTypesBuffer = ParentHiddenTypes;
    HiddenTypes = &HiddenTypesBuffer;

    for (CXXRecordDecl::conversion_iterator I = ConvI; I != ConvE; ++I) {
      CanQualType ConvType(GetConversionType(Context, I.getDecl()));
      bool Hidden = ParentHiddenTypes.count(ConvType);
      if (!Hidden)
        HiddenTypesBuffer.insert(ConvType);

      // If this conversion is hidden and we're in a virtual base,
      // remember that it's hidden along some inheritance path.
      if (Hidden && InVirtual)
        HiddenVBaseCs.insert(cast<NamedDecl>(I.getDecl()->getCanonicalDecl()));

      // If this conversion isn't hidden, add it to the appropriate output.
      else if (!Hidden) {
        AccessSpecifier IAccess
          = CXXRecordDecl::MergeAccess(Access, I.getAccess());

        if (InVirtual)
          VOutput.addDecl(I.getDecl(), IAccess);
        else
          Output.addDecl(Context, I.getDecl(), IAccess);
      }
    }
  }

  // Collect information recursively from any base classes.
  for (const auto &I : Record->bases()) {
    const RecordType *RT = I.getType()->getAs<RecordType>();
    if (!RT) continue;

    AccessSpecifier BaseAccess
      = CXXRecordDecl::MergeAccess(Access, I.getAccessSpecifier());
    bool BaseInVirtual = InVirtual || I.isVirtual();

    auto *Base = cast<CXXRecordDecl>(RT->getDecl());
    CollectVisibleConversions(Context, Base, BaseInVirtual, BaseAccess,
                              *HiddenTypes, Output, VOutput, HiddenVBaseCs);
  }
}

/// Collect the visible conversions of a class.
///
/// This would be extremely straightforward if it weren't for virtual
/// bases.  It might be worth special-casing that, really.
static void CollectVisibleConversions(ASTContext &Context,
                                      CXXRecordDecl *Record,
                                      ASTUnresolvedSet &Output) {
  // The collection of all conversions in virtual bases that we've
  // found.  These will be added to the output as long as they don't
  // appear in the hidden-conversions set.
  UnresolvedSet<8> VBaseCs;

  // The set of conversions in virtual bases that we've determined to
  // be hidden.
  llvm::SmallPtrSet<NamedDecl*, 8> HiddenVBaseCs;

  // The set of types hidden by classes derived from this one.
  llvm::SmallPtrSet<CanQualType, 8> HiddenTypes;

  // Go ahead and collect the direct conversions and add them to the
  // hidden-types set.
  CXXRecordDecl::conversion_iterator ConvI = Record->conversion_begin();
  CXXRecordDecl::conversion_iterator ConvE = Record->conversion_end();
  Output.append(Context, ConvI, ConvE);
  for (; ConvI != ConvE; ++ConvI)
    HiddenTypes.insert(GetConversionType(Context, ConvI.getDecl()));

  // Recursively collect conversions from base classes.
  for (const auto &I : Record->bases()) {
    const RecordType *RT = I.getType()->getAs<RecordType>();
    if (!RT) continue;

    CollectVisibleConversions(Context, cast<CXXRecordDecl>(RT->getDecl()),
                              I.isVirtual(), I.getAccessSpecifier(),
                              HiddenTypes, Output, VBaseCs, HiddenVBaseCs);
  }

  // Add any unhidden conversions provided by virtual bases.
  for (UnresolvedSetIterator I = VBaseCs.begin(), E = VBaseCs.end();
         I != E; ++I) {
    if (!HiddenVBaseCs.count(cast<NamedDecl>(I.getDecl()->getCanonicalDecl())))
      Output.addDecl(Context, I.getDecl(), I.getAccess());
  }
}

/// getVisibleConversionFunctions - get all conversion functions visible
/// in current class; including conversion function templates.
llvm::iterator_range<CXXRecordDecl::conversion_iterator>
CXXRecordDecl::getVisibleConversionFunctions() {
  ASTContext &Ctx = getASTContext();

  ASTUnresolvedSet *Set;
  if (bases_begin() == bases_end()) {
    // If root class, all conversions are visible.
    Set = &data().Conversions.get(Ctx);
  } else {
    Set = &data().VisibleConversions.get(Ctx);
    // If visible conversion list is not evaluated, evaluate it.
    if (!data().ComputedVisibleConversions) {
      CollectVisibleConversions(Ctx, this, *Set);
      data().ComputedVisibleConversions = true;
    }
  }
  return llvm::make_range(Set->begin(), Set->end());
}

void CXXRecordDecl::removeConversion(const NamedDecl *ConvDecl) {
  // This operation is O(N) but extremely rare.  Sema only uses it to
  // remove UsingShadowDecls in a class that were followed by a direct
  // declaration, e.g.:
  //   class A : B {
  //     using B::operator int;
  //     operator int();
  //   };
  // This is uncommon by itself and even more uncommon in conjunction
  // with sufficiently large numbers of directly-declared conversions
  // that asymptotic behavior matters.

  ASTUnresolvedSet &Convs = data().Conversions.get(getASTContext());
  for (unsigned I = 0, E = Convs.size(); I != E; ++I) {
    if (Convs[I].getDecl() == ConvDecl) {
      Convs.erase(I);
      assert(std::find(Convs.begin(), Convs.end(), ConvDecl) == Convs.end()
             && "conversion was found multiple times in unresolved set");
      return;
    }
  }

  llvm_unreachable("conversion not found in set!");
}

CXXRecordDecl *CXXRecordDecl::getInstantiatedFromMemberClass() const {
  if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo())
    return cast<CXXRecordDecl>(MSInfo->getInstantiatedFrom());

  return nullptr;
}

MemberSpecializationInfo *CXXRecordDecl::getMemberSpecializationInfo() const {
  return TemplateOrInstantiation.dyn_cast<MemberSpecializationInfo *>();
}

void
CXXRecordDecl::setInstantiationOfMemberClass(CXXRecordDecl *RD,
                                             TemplateSpecializationKind TSK) {
  assert(TemplateOrInstantiation.isNull() &&
         "Previous template or instantiation?");
  assert(!isa<ClassTemplatePartialSpecializationDecl>(this));
  TemplateOrInstantiation
    = new (getASTContext()) MemberSpecializationInfo(RD, TSK);
}

ClassTemplateDecl *CXXRecordDecl::getDescribedClassTemplate() const {
  return TemplateOrInstantiation.dyn_cast<ClassTemplateDecl *>();
}

void CXXRecordDecl::setDescribedClassTemplate(ClassTemplateDecl *Template) {
  TemplateOrInstantiation = Template;
}

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

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

  return TSK_Undeclared;
}

void
CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
  if (auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
    Spec->setSpecializationKind(TSK);
    return;
  }

  if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
    MSInfo->setTemplateSpecializationKind(TSK);
    return;
  }

  llvm_unreachable("Not a class template or member class specialization");
}

const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
  auto GetDefinitionOrSelf =
      [](const CXXRecordDecl *D) -> const CXXRecordDecl * {
    if (auto *Def = D->getDefinition())
      return Def;
    return D;
  };

  // If it's a class template specialization, find the template or partial
  // specialization from which it was instantiated.
  if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
    auto From = TD->getInstantiatedFrom();
    if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
      while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
        if (NewCTD->isMemberSpecialization())
          break;
        CTD = NewCTD;
      }
      return GetDefinitionOrSelf(CTD->getTemplatedDecl());
    }
    if (auto *CTPSD =
            From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
      while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
        if (NewCTPSD->isMemberSpecialization())
          break;
        CTPSD = NewCTPSD;
      }
      return GetDefinitionOrSelf(CTPSD);
    }
  }

  if (MemberSpecializationInfo *MSInfo = getMemberSpecializationInfo()) {
    if (isTemplateInstantiation(MSInfo->getTemplateSpecializationKind())) {
      const CXXRecordDecl *RD = this;
      while (auto *NewRD = RD->getInstantiatedFromMemberClass())
        RD = NewRD;
      return GetDefinitionOrSelf(RD);
    }
  }

  assert(!isTemplateInstantiation(this->getTemplateSpecializationKind()) &&
         "couldn't find pattern for class template instantiation");
  return nullptr;
}

CXXDestructorDecl *CXXRecordDecl::getDestructor() const {
  ASTContext &Context = getASTContext();
  QualType ClassType = Context.getTypeDeclType(this);

  DeclarationName Name
    = Context.DeclarationNames.getCXXDestructorName(
                                          Context.getCanonicalType(ClassType));

  DeclContext::lookup_result R = lookup(Name);

  return R.empty() ? nullptr : dyn_cast<CXXDestructorDecl>(R.front());
}

bool CXXRecordDecl::isAnyDestructorNoReturn() const {
  // Destructor is noreturn.
  if (const CXXDestructorDecl *Destructor = getDestructor())
    if (Destructor->isNoReturn())
      return true;

  // Check base classes destructor for noreturn.
  for (const auto &Base : bases())
    if (const CXXRecordDecl *RD = Base.getType()->getAsCXXRecordDecl())
      if (RD->isAnyDestructorNoReturn())
        return true;

  // Check fields for noreturn.
  for (const auto *Field : fields())
    if (const CXXRecordDecl *RD =
            Field->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl())
      if (RD->isAnyDestructorNoReturn())
        return true;

  // All destructors are not noreturn.
  return false;
}

static bool isDeclContextInNamespace(const DeclContext *DC) {
  while (!DC->isTranslationUnit()) {
    if (DC->isNamespace())
      return true;
    DC = DC->getParent();
  }
  return false;
}

bool CXXRecordDecl::isInterfaceLike() const {
  assert(hasDefinition() && "checking for interface-like without a definition");
  // All __interfaces are inheritently interface-like.
  if (isInterface())
    return true;

  // Interface-like types cannot have a user declared constructor, destructor,
  // friends, VBases, conversion functions, or fields.  Additionally, lambdas
  // cannot be interface types.
  if (isLambda() || hasUserDeclaredConstructor() ||
      hasUserDeclaredDestructor() || !field_empty() || hasFriends() ||
      getNumVBases() > 0 || conversion_end() - conversion_begin() > 0)
    return false;

  // No interface-like type can have a method with a definition.
  for (const auto *const Method : methods())
    if (Method->isDefined() && !Method->isImplicit())
      return false;

  // Check "Special" types.
  const auto *Uuid = getAttr<UuidAttr>();
  // MS SDK declares IUnknown/IDispatch both in the root of a TU, or in an
  // extern C++ block directly in the TU.  These are only valid if in one
  // of these two situations.
  if (Uuid && isStruct() && !getDeclContext()->isExternCContext() &&
      !isDeclContextInNamespace(getDeclContext()) &&
      ((getName() == "IUnknown" &&
        Uuid->getGuid() == "00000000-0000-0000-C000-000000000046") ||
       (getName() == "IDispatch" &&
        Uuid->getGuid() == "00020400-0000-0000-C000-000000000046"))) {
    if (getNumBases() > 0)
      return false;
    return true;
  }

  // FIXME: Any access specifiers is supposed to make this no longer interface
  // like.

  // If this isn't a 'special' type, it must have a single interface-like base.
  if (getNumBases() != 1)
    return false;

  const auto BaseSpec = *bases_begin();
  if (BaseSpec.isVirtual() || BaseSpec.getAccessSpecifier() != AS_public)
    return false;
  const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl();
  if (Base->isInterface() || !Base->isInterfaceLike())
    return false;
  return true;
}

void CXXRecordDecl::completeDefinition() {
  completeDefinition(nullptr);
}

void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) {
  RecordDecl::completeDefinition();

  // If the class may be abstract (but hasn't been marked as such), check for
  // any pure final overriders.
  if (mayBeAbstract()) {
    CXXFinalOverriderMap MyFinalOverriders;
    if (!FinalOverriders) {
      getFinalOverriders(MyFinalOverriders);
      FinalOverriders = &MyFinalOverriders;
    }

    bool Done = false;
    for (CXXFinalOverriderMap::iterator M = FinalOverriders->begin(),
                                     MEnd = FinalOverriders->end();
         M != MEnd && !Done; ++M) {
      for (OverridingMethods::iterator SO = M->second.begin(),
                                    SOEnd = M->second.end();
           SO != SOEnd && !Done; ++SO) {
        assert(SO->second.size() > 0 &&
               "All virtual functions have overriding virtual functions");

        // C++ [class.abstract]p4:
        //   A class is abstract if it contains or inherits at least one
        //   pure virtual function for which the final overrider is pure
        //   virtual.
        if (SO->second.front().Method->isPure()) {
          data().Abstract = true;
          Done = true;
          break;
        }
      }
    }
  }

  // Set access bits correctly on the directly-declared conversions.
  for (conversion_iterator I = conversion_begin(), E = conversion_end();
       I != E; ++I)
    I.setAccess((*I)->getAccess());
}

bool CXXRecordDecl::mayBeAbstract() const {
  if (data().Abstract || isInvalidDecl() || !data().Polymorphic ||
      isDependentContext())
    return false;

  for (const auto &B : bases()) {
    const auto *BaseDecl =
        cast<CXXRecordDecl>(B.getType()->getAs<RecordType>()->getDecl());
    if (BaseDecl->isAbstract())
      return true;
  }

  return false;
}

void CXXDeductionGuideDecl::anchor() {}

CXXDeductionGuideDecl *CXXDeductionGuideDecl::Create(
    ASTContext &C, DeclContext *DC, SourceLocation StartLoc, bool IsExplicit,
    const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo,
    SourceLocation EndLocation) {
  return new (C, DC) CXXDeductionGuideDecl(C, DC, StartLoc, IsExplicit,
                                           NameInfo, T, TInfo, EndLocation);
}

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

void CXXMethodDecl::anchor() {}

bool CXXMethodDecl::isStatic() const {
  const CXXMethodDecl *MD = getCanonicalDecl();

  if (MD->getStorageClass() == SC_Static)
    return true;

  OverloadedOperatorKind OOK = getDeclName().getCXXOverloadedOperator();
  return isStaticOverloadedOperator(OOK);
}

static bool recursivelyOverrides(const CXXMethodDecl *DerivedMD,
                                 const CXXMethodDecl *BaseMD) {
  for (const CXXMethodDecl *MD : DerivedMD->overridden_methods()) {
    if (MD->getCanonicalDecl() == BaseMD->getCanonicalDecl())
      return true;
    if (recursivelyOverrides(MD, BaseMD))
      return true;
  }
  return false;
}

CXXMethodDecl *
CXXMethodDecl::getCorrespondingMethodInClass(const CXXRecordDecl *RD,
                                             bool MayBeBase) {
  if (this->getParent()->getCanonicalDecl() == RD->getCanonicalDecl())
    return this;

  // Lookup doesn't work for destructors, so handle them separately.
  if (isa<CXXDestructorDecl>(this)) {
    CXXMethodDecl *MD = RD->getDestructor();
    if (MD) {
      if (recursivelyOverrides(MD, this))
        return MD;
      if (MayBeBase && recursivelyOverrides(this, MD))
        return MD;
    }
    return nullptr;
  }

  for (auto *ND : RD->lookup(getDeclName())) {
    auto *MD = dyn_cast<CXXMethodDecl>(ND);
    if (!MD)
      continue;
    if (recursivelyOverrides(MD, this))
      return MD;
    if (MayBeBase && recursivelyOverrides(this, MD))
      return MD;
  }

  for (const auto &I : RD->bases()) {
    const RecordType *RT = I.getType()->getAs<RecordType>();
    if (!RT)
      continue;
    const auto *Base = cast<CXXRecordDecl>(RT->getDecl());
    CXXMethodDecl *T = this->getCorrespondingMethodInClass(Base);
    if (T)
      return T;
  }

  return nullptr;
}

CXXMethodDecl *
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                      SourceLocation StartLoc,
                      const DeclarationNameInfo &NameInfo,
                      QualType T, TypeSourceInfo *TInfo,
                      StorageClass SC, bool isInline,
                      bool isConstexpr, SourceLocation EndLocation) {
  return new (C, RD) CXXMethodDecl(CXXMethod, C, RD, StartLoc, NameInfo,
                                   T, TInfo, SC, isInline, isConstexpr,
                                   EndLocation);
}

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

CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
                                                     bool IsAppleKext) {
  assert(isVirtual() && "this method is expected to be virtual");

  // When building with -fapple-kext, all calls must go through the vtable since
  // the kernel linker can do runtime patching of vtables.
  if (IsAppleKext)
    return nullptr;

  // If the member function is marked 'final', we know that it can't be
  // overridden and can therefore devirtualize it unless it's pure virtual.
  if (hasAttr<FinalAttr>())
    return isPure() ? nullptr : this;

  // If Base is unknown, we cannot devirtualize.
  if (!Base)
    return nullptr;

  // If the base expression (after skipping derived-to-base conversions) is a
  // class prvalue, then we can devirtualize.
  Base = Base->getBestDynamicClassTypeExpr();
  if (Base->isRValue() && Base->getType()->isRecordType())
    return this;

  // If we don't even know what we would call, we can't devirtualize.
  const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();
  if (!BestDynamicDecl)
    return nullptr;

  // There may be a method corresponding to MD in a derived class.
  CXXMethodDecl *DevirtualizedMethod =
      getCorrespondingMethodInClass(BestDynamicDecl);

  // If that method is pure virtual, we can't devirtualize. If this code is
  // reached, the result would be UB, not a direct call to the derived class
  // function, and we can't assume the derived class function is defined.
  if (DevirtualizedMethod->isPure())
    return nullptr;

  // If that method is marked final, we can devirtualize it.
  if (DevirtualizedMethod->hasAttr<FinalAttr>())
    return DevirtualizedMethod;

  // Similarly, if the class itself is marked 'final' it can't be overridden
  // and we can therefore devirtualize the member function call.
  if (BestDynamicDecl->hasAttr<FinalAttr>())
    return DevirtualizedMethod;

  if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
    if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
      if (VD->getType()->isRecordType())
        // This is a record decl. We know the type and can devirtualize it.
        return DevirtualizedMethod;

    return nullptr;
  }

  // We can devirtualize calls on an object accessed by a class member access
  // expression, since by C++11 [basic.life]p6 we know that it can't refer to
  // a derived class object constructed in the same location.
  if (const auto *ME = dyn_cast<MemberExpr>(Base)) {
    const ValueDecl *VD = ME->getMemberDecl();
    return VD->getType()->isRecordType() ? DevirtualizedMethod : nullptr;
  }

  // Likewise for calls on an object accessed by a (non-reference) pointer to
  // member access.
  if (auto *BO = dyn_cast<BinaryOperator>(Base)) {
    if (BO->isPtrMemOp()) {
      auto *MPT = BO->getRHS()->getType()->castAs<MemberPointerType>();
      if (MPT->getPointeeType()->isRecordType())
        return DevirtualizedMethod;
    }
  }

  // We can't devirtualize the call.
  return nullptr;
}

bool CXXMethodDecl::isUsualDeallocationFunction() const {
  if (getOverloadedOperator() != OO_Delete &&
      getOverloadedOperator() != OO_Array_Delete)
    return false;

  // C++ [basic.stc.dynamic.deallocation]p2:
  //   A template instance is never a usual deallocation function,
  //   regardless of its signature.
  if (getPrimaryTemplate())
    return false;

  // C++ [basic.stc.dynamic.deallocation]p2:
  //   If a class T has a member deallocation function named operator delete
  //   with exactly one parameter, then that function is a usual (non-placement)
  //   deallocation function. [...]
  if (getNumParams() == 1)
    return true;
  unsigned UsualParams = 1;

  // C++ P0722:
  //   A destroying operator delete is a usual deallocation function if
  //   removing the std::destroying_delete_t parameter and changing the
  //   first parameter type from T* to void* results in the signature of
  //   a usual deallocation function.
  if (isDestroyingOperatorDelete())
    ++UsualParams;

  // C++ <=14 [basic.stc.dynamic.deallocation]p2:
  //   [...] If class T does not declare such an operator delete but does
  //   declare a member deallocation function named operator delete with
  //   exactly two parameters, the second of which has type std::size_t (18.1),
  //   then this function is a usual deallocation function.
  //
  // C++17 says a usual deallocation function is one with the signature
  //   (void* [, size_t] [, std::align_val_t] [, ...])
  // and all such functions are usual deallocation functions. It's not clear
  // that allowing varargs functions was intentional.
  ASTContext &Context = getASTContext();
  if (UsualParams < getNumParams() &&
      Context.hasSameUnqualifiedType(getParamDecl(UsualParams)->getType(),
                                     Context.getSizeType()))
    ++UsualParams;

  if (UsualParams < getNumParams() &&
      getParamDecl(UsualParams)->getType()->isAlignValT())
    ++UsualParams;

  if (UsualParams != getNumParams())
    return false;

  // In C++17 onwards, all potential usual deallocation functions are actual
  // usual deallocation functions.
  if (Context.getLangOpts().AlignedAllocation)
    return true;

  // This function is a usual deallocation function if there are no
  // single-parameter deallocation functions of the same kind.
  DeclContext::lookup_result R = getDeclContext()->lookup(getDeclName());
  for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();
       I != E; ++I) {
    if (const auto *FD = dyn_cast<FunctionDecl>(*I))
      if (FD->getNumParams() == 1)
        return false;
  }

  return true;
}

bool CXXMethodDecl::isCopyAssignmentOperator() const {
  // C++0x [class.copy]p17:
  //  A user-declared copy assignment operator X::operator= is a non-static
  //  non-template member function of class X with exactly one parameter of
  //  type X, X&, const X&, volatile X& or const volatile X&.
  if (/*operator=*/getOverloadedOperator() != OO_Equal ||
      /*non-static*/ isStatic() ||
      /*non-template*/getPrimaryTemplate() || getDescribedFunctionTemplate() ||
      getNumParams() != 1)
    return false;

  QualType ParamType = getParamDecl(0)->getType();
  if (const auto *Ref = ParamType->getAs<LValueReferenceType>())
    ParamType = Ref->getPointeeType();

  ASTContext &Context = getASTContext();
  QualType ClassType
    = Context.getCanonicalType(Context.getTypeDeclType(getParent()));
  return Context.hasSameUnqualifiedType(ClassType, ParamType);
}

bool CXXMethodDecl::isMoveAssignmentOperator() const {
  // C++0x [class.copy]p19:
  //  A user-declared move assignment operator X::operator= is a non-static
  //  non-template member function of class X with exactly one parameter of type
  //  X&&, const X&&, volatile X&&, or const volatile X&&.
  if (getOverloadedOperator() != OO_Equal || isStatic() ||
      getPrimaryTemplate() || getDescribedFunctionTemplate() ||
      getNumParams() != 1)
    return false;

  QualType ParamType = getParamDecl(0)->getType();
  if (!isa<RValueReferenceType>(ParamType))
    return false;
  ParamType = ParamType->getPointeeType();

  ASTContext &Context = getASTContext();
  QualType ClassType
    = Context.getCanonicalType(Context.getTypeDeclType(getParent()));
  return Context.hasSameUnqualifiedType(ClassType, ParamType);
}

void CXXMethodDecl::addOverriddenMethod(const CXXMethodDecl *MD) {
  assert(MD->isCanonicalDecl() && "Method is not canonical!");
  assert(!MD->getParent()->isDependentContext() &&
         "Can't add an overridden method to a class template!");
  assert(MD->isVirtual() && "Method is not virtual!");

  getASTContext().addOverriddenMethod(this, MD);
}

CXXMethodDecl::method_iterator CXXMethodDecl::begin_overridden_methods() const {
  if (isa<CXXConstructorDecl>(this)) return nullptr;
  return getASTContext().overridden_methods_begin(this);
}

CXXMethodDecl::method_iterator CXXMethodDecl::end_overridden_methods() const {
  if (isa<CXXConstructorDecl>(this)) return nullptr;
  return getASTContext().overridden_methods_end(this);
}

unsigned CXXMethodDecl::size_overridden_methods() const {
  if (isa<CXXConstructorDecl>(this)) return 0;
  return getASTContext().overridden_methods_size(this);
}

CXXMethodDecl::overridden_method_range
CXXMethodDecl::overridden_methods() const {
  if (isa<CXXConstructorDecl>(this))
    return overridden_method_range(nullptr, nullptr);
  return getASTContext().overridden_methods(this);
}

QualType CXXMethodDecl::getThisType(ASTContext &C) const {
  // C++ 9.3.2p1: The type of this in a member function of a class X is X*.
  // If the member function is declared const, the type of this is const X*,
  // if the member function is declared volatile, the type of this is
  // volatile X*, and if the member function is declared const volatile,
  // the type of this is const volatile X*.

  assert(isInstance() && "No 'this' for static methods!");

  QualType ClassTy = C.getTypeDeclType(getParent());
  ClassTy = C.getQualifiedType(ClassTy,
                               Qualifiers::fromCVRUMask(getTypeQualifiers()));
  return C.getPointerType(ClassTy);
}

bool CXXMethodDecl::hasInlineBody() const {
  // If this function is a template instantiation, look at the template from
  // which it was instantiated.
  const FunctionDecl *CheckFn = getTemplateInstantiationPattern();
  if (!CheckFn)
    CheckFn = this;

  const FunctionDecl *fn;
  return CheckFn->isDefined(fn) && !fn->isOutOfLine() &&
         (fn->doesThisDeclarationHaveABody() || fn->willHaveBody());
}

bool CXXMethodDecl::isLambdaStaticInvoker() const {
  const CXXRecordDecl *P = getParent();
  if (P->isLambda()) {
    if (const CXXMethodDecl *StaticInvoker = P->getLambdaStaticInvoker()) {
      if (StaticInvoker == this) return true;
      if (P->isGenericLambda() && this->isFunctionTemplateSpecialization())
        return StaticInvoker == this->getPrimaryTemplate()->getTemplatedDecl();
    }
  }
  return false;
}

CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
                                       TypeSourceInfo *TInfo, bool IsVirtual,
                                       SourceLocation L, Expr *Init,
                                       SourceLocation R,
                                       SourceLocation EllipsisLoc)
    : Initializee(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init),
      LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(IsVirtual),
      IsWritten(false), SourceOrder(0) {}

CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
                                       FieldDecl *Member,
                                       SourceLocation MemberLoc,
                                       SourceLocation L, Expr *Init,
                                       SourceLocation R)
    : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
      LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
      IsWritten(false), SourceOrder(0) {}

CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
                                       IndirectFieldDecl *Member,
                                       SourceLocation MemberLoc,
                                       SourceLocation L, Expr *Init,
                                       SourceLocation R)
    : Initializee(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init),
      LParenLoc(L), RParenLoc(R), IsDelegating(false), IsVirtual(false),
      IsWritten(false), SourceOrder(0) {}

CXXCtorInitializer::CXXCtorInitializer(ASTContext &Context,
                                       TypeSourceInfo *TInfo,
                                       SourceLocation L, Expr *Init,
                                       SourceLocation R)
    : Initializee(TInfo), Init(Init), LParenLoc(L), RParenLoc(R),
      IsDelegating(true), IsVirtual(false), IsWritten(false), SourceOrder(0) {}

TypeLoc CXXCtorInitializer::getBaseClassLoc() const {
  if (isBaseInitializer())
    return Initializee.get<TypeSourceInfo*>()->getTypeLoc();
  else
    return {};
}

const Type *CXXCtorInitializer::getBaseClass() const {
  if (isBaseInitializer())
    return Initializee.get<TypeSourceInfo*>()->getType().getTypePtr();
  else
    return nullptr;
}

SourceLocation CXXCtorInitializer::getSourceLocation() const {
  if (isInClassMemberInitializer())
    return getAnyMember()->getLocation();

  if (isAnyMemberInitializer())
    return getMemberLocation();

  if (const auto *TSInfo = Initializee.get<TypeSourceInfo *>())
    return TSInfo->getTypeLoc().getLocalSourceRange().getBegin();

  return {};
}

SourceRange CXXCtorInitializer::getSourceRange() const {
  if (isInClassMemberInitializer()) {
    FieldDecl *D = getAnyMember();
    if (Expr *I = D->getInClassInitializer())
      return I->getSourceRange();
    return {};
  }

  return SourceRange(getSourceLocation(), getRParenLoc());
}

void CXXConstructorDecl::anchor() {}

CXXConstructorDecl *CXXConstructorDecl::CreateDeserialized(ASTContext &C,
                                                           unsigned ID,
                                                           bool Inherited) {
  unsigned Extra = additionalSizeToAlloc<InheritedConstructor>(Inherited);
  auto *Result = new (C, ID, Extra) CXXConstructorDecl(
      C, nullptr, SourceLocation(), DeclarationNameInfo(), QualType(), nullptr,
      false, false, false, false, InheritedConstructor());
  Result->IsInheritingConstructor = Inherited;
  return Result;
}

CXXConstructorDecl *
CXXConstructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                           SourceLocation StartLoc,
                           const DeclarationNameInfo &NameInfo,
                           QualType T, TypeSourceInfo *TInfo,
                           bool isExplicit, bool isInline,
                           bool isImplicitlyDeclared, bool isConstexpr,
                           InheritedConstructor Inherited) {
  assert(NameInfo.getName().getNameKind()
         == DeclarationName::CXXConstructorName &&
         "Name must refer to a constructor");
  unsigned Extra =
      additionalSizeToAlloc<InheritedConstructor>(Inherited ? 1 : 0);
  return new (C, RD, Extra) CXXConstructorDecl(
      C, RD, StartLoc, NameInfo, T, TInfo, isExplicit, isInline,
      isImplicitlyDeclared, isConstexpr, Inherited);
}

CXXConstructorDecl::init_const_iterator CXXConstructorDecl::init_begin() const {
  return CtorInitializers.get(getASTContext().getExternalSource());
}

CXXConstructorDecl *CXXConstructorDecl::getTargetConstructor() const {
  assert(isDelegatingConstructor() && "Not a delegating constructor!");
  Expr *E = (*init_begin())->getInit()->IgnoreImplicit();
  if (const auto *Construct = dyn_cast<CXXConstructExpr>(E))
    return Construct->getConstructor();

  return nullptr;
}

bool CXXConstructorDecl::isDefaultConstructor() const {
  // C++ [class.ctor]p5:
  //   A default constructor for a class X is a constructor of class
  //   X that can be called without an argument.
  return (getNumParams() == 0) ||
         (getNumParams() > 0 && getParamDecl(0)->hasDefaultArg());
}

bool
CXXConstructorDecl::isCopyConstructor(unsigned &TypeQuals) const {
  return isCopyOrMoveConstructor(TypeQuals) &&
         getParamDecl(0)->getType()->isLValueReferenceType();
}

bool CXXConstructorDecl::isMoveConstructor(unsigned &TypeQuals) const {
  return isCopyOrMoveConstructor(TypeQuals) &&
    getParamDecl(0)->getType()->isRValueReferenceType();
}

/// Determine whether this is a copy or move constructor.
bool CXXConstructorDecl::isCopyOrMoveConstructor(unsigned &TypeQuals) const {
  // C++ [class.copy]p2:
  //   A non-template constructor for class X is a copy constructor
  //   if its first parameter is of type X&, const X&, volatile X& or
  //   const volatile X&, and either there are no other parameters
  //   or else all other parameters have default arguments (8.3.6).
  // C++0x [class.copy]p3:
  //   A non-template constructor for class X is a move constructor if its
  //   first parameter is of type X&&, const X&&, volatile X&&, or
  //   const volatile X&&, and either there are no other parameters or else
  //   all other parameters have default arguments.
  if ((getNumParams() < 1) ||
      (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
      (getPrimaryTemplate() != nullptr) ||
      (getDescribedFunctionTemplate() != nullptr))
    return false;

  const ParmVarDecl *Param = getParamDecl(0);

  // Do we have a reference type?
  const auto *ParamRefType = Param->getType()->getAs<ReferenceType>();
  if (!ParamRefType)
    return false;

  // Is it a reference to our class type?
  ASTContext &Context = getASTContext();

  CanQualType PointeeType
    = Context.getCanonicalType(ParamRefType->getPointeeType());
  CanQualType ClassTy
    = Context.getCanonicalType(Context.getTagDeclType(getParent()));
  if (PointeeType.getUnqualifiedType() != ClassTy)
    return false;

  // FIXME: other qualifiers?

  // We have a copy or move constructor.
  TypeQuals = PointeeType.getCVRQualifiers();
  return true;
}

bool CXXConstructorDecl::isConvertingConstructor(bool AllowExplicit) const {
  // C++ [class.conv.ctor]p1:
  //   A constructor declared without the function-specifier explicit
  //   that can be called with a single parameter specifies a
  //   conversion from the type of its first parameter to the type of
  //   its class. Such a constructor is called a converting
  //   constructor.
  if (isExplicit() && !AllowExplicit)
    return false;

  return (getNumParams() == 0 &&
          getType()->getAs<FunctionProtoType>()->isVariadic()) ||
         (getNumParams() == 1) ||
         (getNumParams() > 1 &&
          (getParamDecl(1)->hasDefaultArg() ||
           getParamDecl(1)->isParameterPack()));
}

bool CXXConstructorDecl::isSpecializationCopyingObject() const {
  if ((getNumParams() < 1) ||
      (getNumParams() > 1 && !getParamDecl(1)->hasDefaultArg()) ||
      (getDescribedFunctionTemplate() != nullptr))
    return false;

  const ParmVarDecl *Param = getParamDecl(0);

  ASTContext &Context = getASTContext();
  CanQualType ParamType = Context.getCanonicalType(Param->getType());

  // Is it the same as our class type?
  CanQualType ClassTy
    = Context.getCanonicalType(Context.getTagDeclType(getParent()));
  if (ParamType.getUnqualifiedType() != ClassTy)
    return false;

  return true;
}

void CXXDestructorDecl::anchor() {}

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

CXXDestructorDecl *
CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                          SourceLocation StartLoc,
                          const DeclarationNameInfo &NameInfo,
                          QualType T, TypeSourceInfo *TInfo,
                          bool isInline, bool isImplicitlyDeclared) {
  assert(NameInfo.getName().getNameKind()
         == DeclarationName::CXXDestructorName &&
         "Name must refer to a destructor");
  return new (C, RD) CXXDestructorDecl(C, RD, StartLoc, NameInfo, T, TInfo,
                                       isInline, isImplicitlyDeclared);
}

void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
  auto *First = cast<CXXDestructorDecl>(getFirstDecl());
  if (OD && !First->OperatorDelete) {
    First->OperatorDelete = OD;
    First->OperatorDeleteThisArg = ThisArg;
    if (auto *L = getASTMutationListener())
      L->ResolvedOperatorDelete(First, OD, ThisArg);
  }
}

void CXXConversionDecl::anchor() {}

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

CXXConversionDecl *
CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD,
                          SourceLocation StartLoc,
                          const DeclarationNameInfo &NameInfo,
                          QualType T, TypeSourceInfo *TInfo,
                          bool isInline, bool isExplicit,
                          bool isConstexpr, SourceLocation EndLocation) {
  assert(NameInfo.getName().getNameKind()
         == DeclarationName::CXXConversionFunctionName &&
         "Name must refer to a conversion function");
  return new (C, RD) CXXConversionDecl(C, RD, StartLoc, NameInfo, T, TInfo,
                                       isInline, isExplicit, isConstexpr,
                                       EndLocation);
}

bool CXXConversionDecl::isLambdaToBlockPointerConversion() const {
  return isImplicit() && getParent()->isLambda() &&
         getConversionType()->isBlockPointerType();
}

void LinkageSpecDecl::anchor() {}

LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
                                         DeclContext *DC,
                                         SourceLocation ExternLoc,
                                         SourceLocation LangLoc,
                                         LanguageIDs Lang,
                                         bool HasBraces) {
  return new (C, DC) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, HasBraces);
}

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

void UsingDirectiveDecl::anchor() {}

UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
                                               SourceLocation L,
                                               SourceLocation NamespaceLoc,
                                           NestedNameSpecifierLoc QualifierLoc,
                                               SourceLocation IdentLoc,
                                               NamedDecl *Used,
                                               DeclContext *CommonAncestor) {
  if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Used))
    Used = NS->getOriginalNamespace();
  return new (C, DC) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc,
                                        IdentLoc, Used, CommonAncestor);
}

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

NamespaceDecl *UsingDirectiveDecl::getNominatedNamespace() {
  if (auto *NA = dyn_cast_or_null<NamespaceAliasDecl>(NominatedNamespace))
    return NA->getNamespace();
  return cast_or_null<NamespaceDecl>(NominatedNamespace);
}

NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
                             SourceLocation StartLoc, SourceLocation IdLoc,
                             IdentifierInfo *Id, NamespaceDecl *PrevDecl)
    : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
      redeclarable_base(C), LocStart(StartLoc),
      AnonOrFirstNamespaceAndInline(nullptr, Inline) {
  setPreviousDecl(PrevDecl);

  if (PrevDecl)
    AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace());
}

NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
                                     bool Inline, SourceLocation StartLoc,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
                                     NamespaceDecl *PrevDecl) {
  return new (C, DC) NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id,
                                   PrevDecl);
}

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

NamespaceDecl *NamespaceDecl::getOriginalNamespace() {
  if (isFirstDecl())
    return this;

  return AnonOrFirstNamespaceAndInline.getPointer();
}

const NamespaceDecl *NamespaceDecl::getOriginalNamespace() const {
  if (isFirstDecl())
    return this;

  return AnonOrFirstNamespaceAndInline.getPointer();
}

bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); }

NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() {
  return getNextRedeclaration();
}

NamespaceDecl *NamespaceDecl::getPreviousDeclImpl() {
  return getPreviousDecl();
}

NamespaceDecl *NamespaceDecl::getMostRecentDeclImpl() {
  return getMostRecentDecl();
}

void NamespaceAliasDecl::anchor() {}

NamespaceAliasDecl *NamespaceAliasDecl::getNextRedeclarationImpl() {
  return getNextRedeclaration();
}

NamespaceAliasDecl *NamespaceAliasDecl::getPreviousDeclImpl() {
  return getPreviousDecl();
}

NamespaceAliasDecl *NamespaceAliasDecl::getMostRecentDeclImpl() {
  return getMostRecentDecl();
}

NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
                                               SourceLocation UsingLoc,
                                               SourceLocation AliasLoc,
                                               IdentifierInfo *Alias,
                                           NestedNameSpecifierLoc QualifierLoc,
                                               SourceLocation IdentLoc,
                                               NamedDecl *Namespace) {
  // FIXME: Preserve the aliased namespace as written.
  if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
    Namespace = NS->getOriginalNamespace();
  return new (C, DC) NamespaceAliasDecl(C, DC, UsingLoc, AliasLoc, Alias,
                                        QualifierLoc, IdentLoc, Namespace);
}

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

void UsingShadowDecl::anchor() {}

UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
                                 SourceLocation Loc, UsingDecl *Using,
                                 NamedDecl *Target)
    : NamedDecl(K, DC, Loc, Using ? Using->getDeclName() : DeclarationName()),
      redeclarable_base(C), UsingOrNextShadow(cast<NamedDecl>(Using)) {
  if (Target)
    setTargetDecl(Target);
  setImplicit();
}

UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, EmptyShell Empty)
    : NamedDecl(K, nullptr, SourceLocation(), DeclarationName()),
      redeclarable_base(C) {}

UsingShadowDecl *
UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell());
}

UsingDecl *UsingShadowDecl::getUsingDecl() const {
  const UsingShadowDecl *Shadow = this;
  while (const auto *NextShadow =
             dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
    Shadow = NextShadow;
  return cast<UsingDecl>(Shadow->UsingOrNextShadow);
}

void ConstructorUsingShadowDecl::anchor() {}

ConstructorUsingShadowDecl *
ConstructorUsingShadowDecl::Create(ASTContext &C, DeclContext *DC,
                                   SourceLocation Loc, UsingDecl *Using,
                                   NamedDecl *Target, bool IsVirtual) {
  return new (C, DC) ConstructorUsingShadowDecl(C, DC, Loc, Using, Target,
                                                IsVirtual);
}

ConstructorUsingShadowDecl *
ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) ConstructorUsingShadowDecl(C, EmptyShell());
}

CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const {
  return getUsingDecl()->getQualifier()->getAsRecordDecl();
}

void UsingDecl::anchor() {}

void UsingDecl::addShadowDecl(UsingShadowDecl *S) {
  assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() &&
         "declaration already in set");
  assert(S->getUsingDecl() == this);

  if (FirstUsingShadow.getPointer())
    S->UsingOrNextShadow = FirstUsingShadow.getPointer();
  FirstUsingShadow.setPointer(S);
}

void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
  assert(std::find(shadow_begin(), shadow_end(), S) != shadow_end() &&
         "declaration not in set");
  assert(S->getUsingDecl() == this);

  // Remove S from the shadow decl chain. This is O(n) but hopefully rare.

  if (FirstUsingShadow.getPointer() == S) {
    FirstUsingShadow.setPointer(
      dyn_cast<UsingShadowDecl>(S->UsingOrNextShadow));
    S->UsingOrNextShadow = this;
    return;
  }

  UsingShadowDecl *Prev = FirstUsingShadow.getPointer();
  while (Prev->UsingOrNextShadow != S)
    Prev = cast<UsingShadowDecl>(Prev->UsingOrNextShadow);
  Prev->UsingOrNextShadow = S->UsingOrNextShadow;
  S->UsingOrNextShadow = this;
}

UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
                             NestedNameSpecifierLoc QualifierLoc,
                             const DeclarationNameInfo &NameInfo,
                             bool HasTypename) {
  return new (C, DC) UsingDecl(DC, UL, QualifierLoc, NameInfo, HasTypename);
}

UsingDecl *UsingDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) UsingDecl(nullptr, SourceLocation(),
                               NestedNameSpecifierLoc(), DeclarationNameInfo(),
                               false);
}

SourceRange UsingDecl::getSourceRange() const {
  SourceLocation Begin = isAccessDeclaration()
    ? getQualifierLoc().getBeginLoc() : UsingLocation;
  return SourceRange(Begin, getNameInfo().getEndLoc());
}

void UsingPackDecl::anchor() {}

UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC,
                                     NamedDecl *InstantiatedFrom,
                                     ArrayRef<NamedDecl *> UsingDecls) {
  size_t Extra = additionalSizeToAlloc<NamedDecl *>(UsingDecls.size());
  return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls);
}

UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID,
                                                 unsigned NumExpansions) {
  size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions);
  auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None);
  Result->NumExpansions = NumExpansions;
  auto *Trail = Result->getTrailingObjects<NamedDecl *>();
  for (unsigned I = 0; I != NumExpansions; ++I)
    new (Trail + I) NamedDecl*(nullptr);
  return Result;
}

void UnresolvedUsingValueDecl::anchor() {}

UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
                                 SourceLocation UsingLoc,
                                 NestedNameSpecifierLoc QualifierLoc,
                                 const DeclarationNameInfo &NameInfo,
                                 SourceLocation EllipsisLoc) {
  return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
                                              QualifierLoc, NameInfo,
                                              EllipsisLoc);
}

UnresolvedUsingValueDecl *
UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
  return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(),
                                              SourceLocation(),
                                              NestedNameSpecifierLoc(),
                                              DeclarationNameInfo(),
                                              SourceLocation());
}

SourceRange UnresolvedUsingValueDecl::getSourceRange() const {
  SourceLocation Begin = isAccessDeclaration()
    ? getQualifierLoc().getBeginLoc() : UsingLocation;
  return SourceRange(Begin, getNameInfo().getEndLoc());
}

void UnresolvedUsingTypenameDecl::anchor() {}

UnresolvedUsingTypenameDecl *
UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
                                    SourceLocation UsingLoc,
                                    SourceLocation TypenameLoc,
                                    NestedNameSpecifierLoc QualifierLoc,
                                    SourceLocation TargetNameLoc,
                                    DeclarationName TargetName,
                                    SourceLocation EllipsisLoc) {
  return new (C, DC) UnresolvedUsingTypenameDecl(
      DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc,
      TargetName.getAsIdentifierInfo(), EllipsisLoc);
}

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

void StaticAssertDecl::anchor() {}

StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,
                                           SourceLocation StaticAssertLoc,
                                           Expr *AssertExpr,
                                           StringLiteral *Message,
                                           SourceLocation RParenLoc,
                                           bool Failed) {
  return new (C, DC) StaticAssertDecl(DC, StaticAssertLoc, AssertExpr, Message,
                                      RParenLoc, Failed);
}

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

void BindingDecl::anchor() {}

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

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

VarDecl *BindingDecl::getHoldingVar() const {
  Expr *B = getBinding();
  if (!B)
    return nullptr;
  auto *DRE = dyn_cast<DeclRefExpr>(B->IgnoreImplicit());
  if (!DRE)
    return nullptr;

  auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
  assert(VD->isImplicit() && "holding var for binding decl not implicit");
  return VD;
}

void DecompositionDecl::anchor() {}

DecompositionDecl *DecompositionDecl::Create(ASTContext &C, DeclContext *DC,
                                             SourceLocation StartLoc,
                                             SourceLocation LSquareLoc,
                                             QualType T, TypeSourceInfo *TInfo,
                                             StorageClass SC,
                                             ArrayRef<BindingDecl *> Bindings) {
  size_t Extra = additionalSizeToAlloc<BindingDecl *>(Bindings.size());
  return new (C, DC, Extra)
      DecompositionDecl(C, DC, StartLoc, LSquareLoc, T, TInfo, SC, Bindings);
}

DecompositionDecl *DecompositionDecl::CreateDeserialized(ASTContext &C,
                                                         unsigned ID,
                                                         unsigned NumBindings) {
  size_t Extra = additionalSizeToAlloc<BindingDecl *>(NumBindings);
  auto *Result = new (C, ID, Extra)
      DecompositionDecl(C, nullptr, SourceLocation(), SourceLocation(),
                        QualType(), nullptr, StorageClass(), None);
  // Set up and clean out the bindings array.
  Result->NumBindings = NumBindings;
  auto *Trail = Result->getTrailingObjects<BindingDecl *>();
  for (unsigned I = 0; I != NumBindings; ++I)
    new (Trail + I) BindingDecl*(nullptr);
  return Result;
}

void DecompositionDecl::printName(llvm::raw_ostream &os) const {
  os << '[';
  bool Comma = false;
  for (const auto *B : bindings()) {
    if (Comma)
      os << ", ";
    B->printName(os);
    Comma = true;
  }
  os << ']';
}

MSPropertyDecl *MSPropertyDecl::Create(ASTContext &C, DeclContext *DC,
                                       SourceLocation L, DeclarationName N,
                                       QualType T, TypeSourceInfo *TInfo,
                                       SourceLocation StartL,
                                       IdentifierInfo *Getter,
                                       IdentifierInfo *Setter) {
  return new (C, DC) MSPropertyDecl(DC, L, N, T, TInfo, StartL, Getter, Setter);
}

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

static const char *getAccessName(AccessSpecifier AS) {
  switch (AS) {
    case AS_none:
      llvm_unreachable("Invalid access specifier!");
    case AS_public:
      return "public";
    case AS_private:
      return "private";
    case AS_protected:
      return "protected";
  }
  llvm_unreachable("Invalid access specifier!");
}

const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
                                           AccessSpecifier AS) {
  return DB << getAccessName(AS);
}

const PartialDiagnostic &clang::operator<<(const PartialDiagnostic &DB,
                                           AccessSpecifier AS) {
  return DB << getAccessName(AS);
}
