//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for C++ declarations.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/EvaluatedExprVisitor.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/LiteralSupport.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/CXXFieldCollector.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include <map>
#include <set>

using namespace clang;

//===----------------------------------------------------------------------===//
// CheckDefaultArgumentVisitor
//===----------------------------------------------------------------------===//

namespace {
  /// CheckDefaultArgumentVisitor - C++ [dcl.fct.default] Traverses
  /// the default argument of a parameter to determine whether it
  /// contains any ill-formed subexpressions. For example, this will
  /// diagnose the use of local variables or parameters within the
  /// default argument expression.
  class CheckDefaultArgumentVisitor
    : public StmtVisitor<CheckDefaultArgumentVisitor, bool> {
    Expr *DefaultArg;
    Sema *S;

  public:
    CheckDefaultArgumentVisitor(Expr *defarg, Sema *s)
        : DefaultArg(defarg), S(s) {}

    bool VisitExpr(Expr *Node);
    bool VisitDeclRefExpr(DeclRefExpr *DRE);
    bool VisitCXXThisExpr(CXXThisExpr *ThisE);
    bool VisitLambdaExpr(LambdaExpr *Lambda);
    bool VisitPseudoObjectExpr(PseudoObjectExpr *POE);
  };

  /// VisitExpr - Visit all of the children of this expression.
  bool CheckDefaultArgumentVisitor::VisitExpr(Expr *Node) {
    bool IsInvalid = false;
    for (Stmt *SubStmt : Node->children())
      IsInvalid |= Visit(SubStmt);
    return IsInvalid;
  }

  /// VisitDeclRefExpr - Visit a reference to a declaration, to
  /// determine whether this declaration can be used in the default
  /// argument expression.
  bool CheckDefaultArgumentVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) {
    NamedDecl *Decl = DRE->getDecl();
    if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(Decl)) {
      // C++ [dcl.fct.default]p9
      //   Default arguments are evaluated each time the function is
      //   called. The order of evaluation of function arguments is
      //   unspecified. Consequently, parameters of a function shall not
      //   be used in default argument expressions, even if they are not
      //   evaluated. Parameters of a function declared before a default
      //   argument expression are in scope and can hide namespace and
      //   class member names.
      return S->Diag(DRE->getBeginLoc(),
                     diag::err_param_default_argument_references_param)
             << Param->getDeclName() << DefaultArg->getSourceRange();
    } else if (VarDecl *VDecl = dyn_cast<VarDecl>(Decl)) {
      // C++ [dcl.fct.default]p7
      //   Local variables shall not be used in default argument
      //   expressions.
      if (VDecl->isLocalVarDecl())
        return S->Diag(DRE->getBeginLoc(),
                       diag::err_param_default_argument_references_local)
               << VDecl->getDeclName() << DefaultArg->getSourceRange();
    }

    return false;
  }

  /// VisitCXXThisExpr - Visit a C++ "this" expression.
  bool CheckDefaultArgumentVisitor::VisitCXXThisExpr(CXXThisExpr *ThisE) {
    // C++ [dcl.fct.default]p8:
    //   The keyword this shall not be used in a default argument of a
    //   member function.
    return S->Diag(ThisE->getBeginLoc(),
                   diag::err_param_default_argument_references_this)
           << ThisE->getSourceRange();
  }

  bool CheckDefaultArgumentVisitor::VisitPseudoObjectExpr(PseudoObjectExpr *POE) {
    bool Invalid = false;
    for (PseudoObjectExpr::semantics_iterator
           i = POE->semantics_begin(), e = POE->semantics_end(); i != e; ++i) {
      Expr *E = *i;

      // Look through bindings.
      if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
        E = OVE->getSourceExpr();
        assert(E && "pseudo-object binding without source expression?");
      }

      Invalid |= Visit(E);
    }
    return Invalid;
  }

  bool CheckDefaultArgumentVisitor::VisitLambdaExpr(LambdaExpr *Lambda) {
    // C++11 [expr.lambda.prim]p13:
    //   A lambda-expression appearing in a default argument shall not
    //   implicitly or explicitly capture any entity.
    if (Lambda->capture_begin() == Lambda->capture_end())
      return false;

    return S->Diag(Lambda->getBeginLoc(), diag::err_lambda_capture_default_arg);
  }
}

void
Sema::ImplicitExceptionSpecification::CalledDecl(SourceLocation CallLoc,
                                                 const CXXMethodDecl *Method) {
  // If we have an MSAny spec already, don't bother.
  if (!Method || ComputedEST == EST_MSAny)
    return;

  const FunctionProtoType *Proto
    = Method->getType()->getAs<FunctionProtoType>();
  Proto = Self->ResolveExceptionSpec(CallLoc, Proto);
  if (!Proto)
    return;

  ExceptionSpecificationType EST = Proto->getExceptionSpecType();

  // If we have a throw-all spec at this point, ignore the function.
  if (ComputedEST == EST_None)
    return;

  if (EST == EST_None && Method->hasAttr<NoThrowAttr>())
    EST = EST_BasicNoexcept;

  switch (EST) {
  case EST_Unparsed:
  case EST_Uninstantiated:
  case EST_Unevaluated:
    llvm_unreachable("should not see unresolved exception specs here");

  // If this function can throw any exceptions, make a note of that.
  case EST_MSAny:
  case EST_None:
    // FIXME: Whichever we see last of MSAny and None determines our result.
    // We should make a consistent, order-independent choice here.
    ClearExceptions();
    ComputedEST = EST;
    return;
  case EST_NoexceptFalse:
    ClearExceptions();
    ComputedEST = EST_None;
    return;
  // FIXME: If the call to this decl is using any of its default arguments, we
  // need to search them for potentially-throwing calls.
  // If this function has a basic noexcept, it doesn't affect the outcome.
  case EST_BasicNoexcept:
  case EST_NoexceptTrue:
  case EST_NoThrow:
    return;
  // If we're still at noexcept(true) and there's a throw() callee,
  // change to that specification.
  case EST_DynamicNone:
    if (ComputedEST == EST_BasicNoexcept)
      ComputedEST = EST_DynamicNone;
    return;
  case EST_DependentNoexcept:
    llvm_unreachable(
        "should not generate implicit declarations for dependent cases");
  case EST_Dynamic:
    break;
  }
  assert(EST == EST_Dynamic && "EST case not considered earlier.");
  assert(ComputedEST != EST_None &&
         "Shouldn't collect exceptions when throw-all is guaranteed.");
  ComputedEST = EST_Dynamic;
  // Record the exceptions in this function's exception specification.
  for (const auto &E : Proto->exceptions())
    if (ExceptionsSeen.insert(Self->Context.getCanonicalType(E)).second)
      Exceptions.push_back(E);
}

void Sema::ImplicitExceptionSpecification::CalledExpr(Expr *E) {
  if (!E || ComputedEST == EST_MSAny)
    return;

  // FIXME:
  //
  // C++0x [except.spec]p14:
  //   [An] implicit exception-specification specifies the type-id T if and
  // only if T is allowed by the exception-specification of a function directly
  // invoked by f's implicit definition; f shall allow all exceptions if any
  // function it directly invokes allows all exceptions, and f shall allow no
  // exceptions if every function it directly invokes allows no exceptions.
  //
  // Note in particular that if an implicit exception-specification is generated
  // for a function containing a throw-expression, that specification can still
  // be noexcept(true).
  //
  // Note also that 'directly invoked' is not defined in the standard, and there
  // is no indication that we should only consider potentially-evaluated calls.
  //
  // Ultimately we should implement the intent of the standard: the exception
  // specification should be the set of exceptions which can be thrown by the
  // implicit definition. For now, we assume that any non-nothrow expression can
  // throw any exception.

  if (Self->canThrow(E))
    ComputedEST = EST_None;
}

bool
Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
                              SourceLocation EqualLoc) {
  if (RequireCompleteType(Param->getLocation(), Param->getType(),
                          diag::err_typecheck_decl_incomplete_type)) {
    Param->setInvalidDecl();
    return true;
  }

  // C++ [dcl.fct.default]p5
  //   A default argument expression is implicitly converted (clause
  //   4) to the parameter type. The default argument expression has
  //   the same semantic constraints as the initializer expression in
  //   a declaration of a variable of the parameter type, using the
  //   copy-initialization semantics (8.5).
  InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
                                                                    Param);
  InitializationKind Kind = InitializationKind::CreateCopy(Param->getLocation(),
                                                           EqualLoc);
  InitializationSequence InitSeq(*this, Entity, Kind, Arg);
  ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Arg);
  if (Result.isInvalid())
    return true;
  Arg = Result.getAs<Expr>();

  CheckCompletedExpr(Arg, EqualLoc);
  Arg = MaybeCreateExprWithCleanups(Arg);

  // Okay: add the default argument to the parameter
  Param->setDefaultArg(Arg);

  // We have already instantiated this parameter; provide each of the
  // instantiations with the uninstantiated default argument.
  UnparsedDefaultArgInstantiationsMap::iterator InstPos
    = UnparsedDefaultArgInstantiations.find(Param);
  if (InstPos != UnparsedDefaultArgInstantiations.end()) {
    for (unsigned I = 0, N = InstPos->second.size(); I != N; ++I)
      InstPos->second[I]->setUninstantiatedDefaultArg(Arg);

    // We're done tracking this parameter's instantiations.
    UnparsedDefaultArgInstantiations.erase(InstPos);
  }

  return false;
}

/// ActOnParamDefaultArgument - Check whether the default argument
/// provided for a function parameter is well-formed. If so, attach it
/// to the parameter declaration.
void
Sema::ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc,
                                Expr *DefaultArg) {
  if (!param || !DefaultArg)
    return;

  ParmVarDecl *Param = cast<ParmVarDecl>(param);
  UnparsedDefaultArgLocs.erase(Param);

  // Default arguments are only permitted in C++
  if (!getLangOpts().CPlusPlus) {
    Diag(EqualLoc, diag::err_param_default_argument)
      << DefaultArg->getSourceRange();
    Param->setInvalidDecl();
    return;
  }

  // Check for unexpanded parameter packs.
  if (DiagnoseUnexpandedParameterPack(DefaultArg, UPPC_DefaultArgument)) {
    Param->setInvalidDecl();
    return;
  }

  // C++11 [dcl.fct.default]p3
  //   A default argument expression [...] shall not be specified for a
  //   parameter pack.
  if (Param->isParameterPack()) {
    Diag(EqualLoc, diag::err_param_default_argument_on_parameter_pack)
        << DefaultArg->getSourceRange();
    return;
  }

  // Check that the default argument is well-formed
  CheckDefaultArgumentVisitor DefaultArgChecker(DefaultArg, this);
  if (DefaultArgChecker.Visit(DefaultArg)) {
    Param->setInvalidDecl();
    return;
  }

  SetParamDefaultArgument(Param, DefaultArg, EqualLoc);
}

/// ActOnParamUnparsedDefaultArgument - We've seen a default
/// argument for a function parameter, but we can't parse it yet
/// because we're inside a class definition. Note that this default
/// argument will be parsed later.
void Sema::ActOnParamUnparsedDefaultArgument(Decl *param,
                                             SourceLocation EqualLoc,
                                             SourceLocation ArgLoc) {
  if (!param)
    return;

  ParmVarDecl *Param = cast<ParmVarDecl>(param);
  Param->setUnparsedDefaultArg();
  UnparsedDefaultArgLocs[Param] = ArgLoc;
}

/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
void Sema::ActOnParamDefaultArgumentError(Decl *param,
                                          SourceLocation EqualLoc) {
  if (!param)
    return;

  ParmVarDecl *Param = cast<ParmVarDecl>(param);
  Param->setInvalidDecl();
  UnparsedDefaultArgLocs.erase(Param);
  Param->setDefaultArg(new(Context)
                       OpaqueValueExpr(EqualLoc,
                                       Param->getType().getNonReferenceType(),
                                       VK_RValue));
}

/// CheckExtraCXXDefaultArguments - Check for any extra default
/// arguments in the declarator, which is not a function declaration
/// or definition and therefore is not permitted to have default
/// arguments. This routine should be invoked for every declarator
/// that is not a function declaration or definition.
void Sema::CheckExtraCXXDefaultArguments(Declarator &D) {
  // C++ [dcl.fct.default]p3
  //   A default argument expression shall be specified only in the
  //   parameter-declaration-clause of a function declaration or in a
  //   template-parameter (14.1). It shall not be specified for a
  //   parameter pack. If it is specified in a
  //   parameter-declaration-clause, it shall not occur within a
  //   declarator or abstract-declarator of a parameter-declaration.
  bool MightBeFunction = D.isFunctionDeclarationContext();
  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
    DeclaratorChunk &chunk = D.getTypeObject(i);
    if (chunk.Kind == DeclaratorChunk::Function) {
      if (MightBeFunction) {
        // This is a function declaration. It can have default arguments, but
        // keep looking in case its return type is a function type with default
        // arguments.
        MightBeFunction = false;
        continue;
      }
      for (unsigned argIdx = 0, e = chunk.Fun.NumParams; argIdx != e;
           ++argIdx) {
        ParmVarDecl *Param = cast<ParmVarDecl>(chunk.Fun.Params[argIdx].Param);
        if (Param->hasUnparsedDefaultArg()) {
          std::unique_ptr<CachedTokens> Toks =
              std::move(chunk.Fun.Params[argIdx].DefaultArgTokens);
          SourceRange SR;
          if (Toks->size() > 1)
            SR = SourceRange((*Toks)[1].getLocation(),
                             Toks->back().getLocation());
          else
            SR = UnparsedDefaultArgLocs[Param];
          Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
            << SR;
        } else if (Param->getDefaultArg()) {
          Diag(Param->getLocation(), diag::err_param_default_argument_nonfunc)
            << Param->getDefaultArg()->getSourceRange();
          Param->setDefaultArg(nullptr);
        }
      }
    } else if (chunk.Kind != DeclaratorChunk::Paren) {
      MightBeFunction = false;
    }
  }
}

static bool functionDeclHasDefaultArgument(const FunctionDecl *FD) {
  for (unsigned NumParams = FD->getNumParams(); NumParams > 0; --NumParams) {
    const ParmVarDecl *PVD = FD->getParamDecl(NumParams-1);
    if (!PVD->hasDefaultArg())
      return false;
    if (!PVD->hasInheritedDefaultArg())
      return true;
  }
  return false;
}

/// MergeCXXFunctionDecl - Merge two declarations of the same C++
/// function, once we already know that they have the same
/// type. Subroutine of MergeFunctionDecl. Returns true if there was an
/// error, false otherwise.
bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old,
                                Scope *S) {
  bool Invalid = false;

  // The declaration context corresponding to the scope is the semantic
  // parent, unless this is a local function declaration, in which case
  // it is that surrounding function.
  DeclContext *ScopeDC = New->isLocalExternDecl()
                             ? New->getLexicalDeclContext()
                             : New->getDeclContext();

  // Find the previous declaration for the purpose of default arguments.
  FunctionDecl *PrevForDefaultArgs = Old;
  for (/**/; PrevForDefaultArgs;
       // Don't bother looking back past the latest decl if this is a local
       // extern declaration; nothing else could work.
       PrevForDefaultArgs = New->isLocalExternDecl()
                                ? nullptr
                                : PrevForDefaultArgs->getPreviousDecl()) {
    // Ignore hidden declarations.
    if (!LookupResult::isVisible(*this, PrevForDefaultArgs))
      continue;

    if (S && !isDeclInScope(PrevForDefaultArgs, ScopeDC, S) &&
        !New->isCXXClassMember()) {
      // Ignore default arguments of old decl if they are not in
      // the same scope and this is not an out-of-line definition of
      // a member function.
      continue;
    }

    if (PrevForDefaultArgs->isLocalExternDecl() != New->isLocalExternDecl()) {
      // If only one of these is a local function declaration, then they are
      // declared in different scopes, even though isDeclInScope may think
      // they're in the same scope. (If both are local, the scope check is
      // sufficient, and if neither is local, then they are in the same scope.)
      continue;
    }

    // We found the right previous declaration.
    break;
  }

  // C++ [dcl.fct.default]p4:
  //   For non-template functions, default arguments can be added in
  //   later declarations of a function in the same
  //   scope. Declarations in different scopes have completely
  //   distinct sets of default arguments. That is, declarations in
  //   inner scopes do not acquire default arguments from
  //   declarations in outer scopes, and vice versa. In a given
  //   function declaration, all parameters subsequent to a
  //   parameter with a default argument shall have default
  //   arguments supplied in this or previous declarations. A
  //   default argument shall not be redefined by a later
  //   declaration (not even to the same value).
  //
  // C++ [dcl.fct.default]p6:
  //   Except for member functions of class templates, the default arguments
  //   in a member function definition that appears outside of the class
  //   definition are added to the set of default arguments provided by the
  //   member function declaration in the class definition.
  for (unsigned p = 0, NumParams = PrevForDefaultArgs
                                       ? PrevForDefaultArgs->getNumParams()
                                       : 0;
       p < NumParams; ++p) {
    ParmVarDecl *OldParam = PrevForDefaultArgs->getParamDecl(p);
    ParmVarDecl *NewParam = New->getParamDecl(p);

    bool OldParamHasDfl = OldParam ? OldParam->hasDefaultArg() : false;
    bool NewParamHasDfl = NewParam->hasDefaultArg();

    if (OldParamHasDfl && NewParamHasDfl) {
      unsigned DiagDefaultParamID =
        diag::err_param_default_argument_redefinition;

      // MSVC accepts that default parameters be redefined for member functions
      // of template class. The new default parameter's value is ignored.
      Invalid = true;
      if (getLangOpts().MicrosoftExt) {
        CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(New);
        if (MD && MD->getParent()->getDescribedClassTemplate()) {
          // Merge the old default argument into the new parameter.
          NewParam->setHasInheritedDefaultArg();
          if (OldParam->hasUninstantiatedDefaultArg())
            NewParam->setUninstantiatedDefaultArg(
                                      OldParam->getUninstantiatedDefaultArg());
          else
            NewParam->setDefaultArg(OldParam->getInit());
          DiagDefaultParamID = diag::ext_param_default_argument_redefinition;
          Invalid = false;
        }
      }

      // FIXME: If we knew where the '=' was, we could easily provide a fix-it
      // hint here. Alternatively, we could walk the type-source information
      // for NewParam to find the last source location in the type... but it
      // isn't worth the effort right now. This is the kind of test case that
      // is hard to get right:
      //   int f(int);
      //   void g(int (*fp)(int) = f);
      //   void g(int (*fp)(int) = &f);
      Diag(NewParam->getLocation(), DiagDefaultParamID)
        << NewParam->getDefaultArgRange();

      // Look for the function declaration where the default argument was
      // actually written, which may be a declaration prior to Old.
      for (auto Older = PrevForDefaultArgs;
           OldParam->hasInheritedDefaultArg(); /**/) {
        Older = Older->getPreviousDecl();
        OldParam = Older->getParamDecl(p);
      }

      Diag(OldParam->getLocation(), diag::note_previous_definition)
        << OldParam->getDefaultArgRange();
    } else if (OldParamHasDfl) {
      // Merge the old default argument into the new parameter unless the new
      // function is a friend declaration in a template class. In the latter
      // case the default arguments will be inherited when the friend
      // declaration will be instantiated.
      if (New->getFriendObjectKind() == Decl::FOK_None ||
          !New->getLexicalDeclContext()->isDependentContext()) {
        // It's important to use getInit() here;  getDefaultArg()
        // strips off any top-level ExprWithCleanups.
        NewParam->setHasInheritedDefaultArg();
        if (OldParam->hasUnparsedDefaultArg())
          NewParam->setUnparsedDefaultArg();
        else if (OldParam->hasUninstantiatedDefaultArg())
          NewParam->setUninstantiatedDefaultArg(
                                       OldParam->getUninstantiatedDefaultArg());
        else
          NewParam->setDefaultArg(OldParam->getInit());
      }
    } else if (NewParamHasDfl) {
      if (New->getDescribedFunctionTemplate()) {
        // Paragraph 4, quoted above, only applies to non-template functions.
        Diag(NewParam->getLocation(),
             diag::err_param_default_argument_template_redecl)
          << NewParam->getDefaultArgRange();
        Diag(PrevForDefaultArgs->getLocation(),
             diag::note_template_prev_declaration)
            << false;
      } else if (New->getTemplateSpecializationKind()
                   != TSK_ImplicitInstantiation &&
                 New->getTemplateSpecializationKind() != TSK_Undeclared) {
        // C++ [temp.expr.spec]p21:
        //   Default function arguments shall not be specified in a declaration
        //   or a definition for one of the following explicit specializations:
        //     - the explicit specialization of a function template;
        //     - the explicit specialization of a member function template;
        //     - the explicit specialization of a member function of a class
        //       template where the class template specialization to which the
        //       member function specialization belongs is implicitly
        //       instantiated.
        Diag(NewParam->getLocation(), diag::err_template_spec_default_arg)
          << (New->getTemplateSpecializationKind() ==TSK_ExplicitSpecialization)
          << New->getDeclName()
          << NewParam->getDefaultArgRange();
      } else if (New->getDeclContext()->isDependentContext()) {
        // C++ [dcl.fct.default]p6 (DR217):
        //   Default arguments for a member function of a class template shall
        //   be specified on the initial declaration of the member function
        //   within the class template.
        //
        // Reading the tea leaves a bit in DR217 and its reference to DR205
        // leads me to the conclusion that one cannot add default function
        // arguments for an out-of-line definition of a member function of a
        // dependent type.
        int WhichKind = 2;
        if (CXXRecordDecl *Record
              = dyn_cast<CXXRecordDecl>(New->getDeclContext())) {
          if (Record->getDescribedClassTemplate())
            WhichKind = 0;
          else if (isa<ClassTemplatePartialSpecializationDecl>(Record))
            WhichKind = 1;
          else
            WhichKind = 2;
        }

        Diag(NewParam->getLocation(),
             diag::err_param_default_argument_member_template_redecl)
          << WhichKind
          << NewParam->getDefaultArgRange();
      }
    }
  }

  // DR1344: If a default argument is added outside a class definition and that
  // default argument makes the function a special member function, the program
  // is ill-formed. This can only happen for constructors.
  if (isa<CXXConstructorDecl>(New) &&
      New->getMinRequiredArguments() < Old->getMinRequiredArguments()) {
    CXXSpecialMember NewSM = getSpecialMember(cast<CXXMethodDecl>(New)),
                     OldSM = getSpecialMember(cast<CXXMethodDecl>(Old));
    if (NewSM != OldSM) {
      ParmVarDecl *NewParam = New->getParamDecl(New->getMinRequiredArguments());
      assert(NewParam->hasDefaultArg());
      Diag(NewParam->getLocation(), diag::err_default_arg_makes_ctor_special)
        << NewParam->getDefaultArgRange() << NewSM;
      Diag(Old->getLocation(), diag::note_previous_declaration);
    }
  }

  const FunctionDecl *Def;
  // C++11 [dcl.constexpr]p1: If any declaration of a function or function
  // template has a constexpr specifier then all its declarations shall
  // contain the constexpr specifier.
  if (New->isConstexpr() != Old->isConstexpr()) {
    Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch)
      << New << New->isConstexpr();
    Diag(Old->getLocation(), diag::note_previous_declaration);
    Invalid = true;
  } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() &&
             Old->isDefined(Def) &&
             // If a friend function is inlined but does not have 'inline'
             // specifier, it is a definition. Do not report attribute conflict
             // in this case, redefinition will be diagnosed later.
             (New->isInlineSpecified() ||
              New->getFriendObjectKind() == Decl::FOK_None)) {
    // C++11 [dcl.fcn.spec]p4:
    //   If the definition of a function appears in a translation unit before its
    //   first declaration as inline, the program is ill-formed.
    Diag(New->getLocation(), diag::err_inline_decl_follows_def) << New;
    Diag(Def->getLocation(), diag::note_previous_definition);
    Invalid = true;
  }

  // C++17 [temp.deduct.guide]p3:
  //   Two deduction guide declarations in the same translation unit
  //   for the same class template shall not have equivalent
  //   parameter-declaration-clauses.
  if (isa<CXXDeductionGuideDecl>(New) &&
      !New->isFunctionTemplateSpecialization()) {
    Diag(New->getLocation(), diag::err_deduction_guide_redeclared);
    Diag(Old->getLocation(), diag::note_previous_declaration);
  }

  // C++11 [dcl.fct.default]p4: If a friend declaration specifies a default
  // argument expression, that declaration shall be a definition and shall be
  // the only declaration of the function or function template in the
  // translation unit.
  if (Old->getFriendObjectKind() == Decl::FOK_Undeclared &&
      functionDeclHasDefaultArgument(Old)) {
    Diag(New->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
    Diag(Old->getLocation(), diag::note_previous_declaration);
    Invalid = true;
  }

  return Invalid;
}

NamedDecl *
Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
                                   MultiTemplateParamsArg TemplateParamLists) {
  assert(D.isDecompositionDeclarator());
  const DecompositionDeclarator &Decomp = D.getDecompositionDeclarator();

  // The syntax only allows a decomposition declarator as a simple-declaration,
  // a for-range-declaration, or a condition in Clang, but we parse it in more
  // cases than that.
  if (!D.mayHaveDecompositionDeclarator()) {
    Diag(Decomp.getLSquareLoc(), diag::err_decomp_decl_context)
      << Decomp.getSourceRange();
    return nullptr;
  }

  if (!TemplateParamLists.empty()) {
    // FIXME: There's no rule against this, but there are also no rules that
    // would actually make it usable, so we reject it for now.
    Diag(TemplateParamLists.front()->getTemplateLoc(),
         diag::err_decomp_decl_template);
    return nullptr;
  }

  Diag(Decomp.getLSquareLoc(),
       !getLangOpts().CPlusPlus17
           ? diag::ext_decomp_decl
           : D.getContext() == DeclaratorContext::ConditionContext
                 ? diag::ext_decomp_decl_cond
                 : diag::warn_cxx14_compat_decomp_decl)
      << Decomp.getSourceRange();

  // The semantic context is always just the current context.
  DeclContext *const DC = CurContext;

  // C++17 [dcl.dcl]/8:
  //   The decl-specifier-seq shall contain only the type-specifier auto
  //   and cv-qualifiers.
  // C++2a [dcl.dcl]/8:
  //   If decl-specifier-seq contains any decl-specifier other than static,
  //   thread_local, auto, or cv-qualifiers, the program is ill-formed.
  auto &DS = D.getDeclSpec();
  {
    SmallVector<StringRef, 8> BadSpecifiers;
    SmallVector<SourceLocation, 8> BadSpecifierLocs;
    SmallVector<StringRef, 8> CPlusPlus20Specifiers;
    SmallVector<SourceLocation, 8> CPlusPlus20SpecifierLocs;
    if (auto SCS = DS.getStorageClassSpec()) {
      if (SCS == DeclSpec::SCS_static) {
        CPlusPlus20Specifiers.push_back(DeclSpec::getSpecifierName(SCS));
        CPlusPlus20SpecifierLocs.push_back(DS.getStorageClassSpecLoc());
      } else {
        BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS));
        BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc());
      }
    }
    if (auto TSCS = DS.getThreadStorageClassSpec()) {
      CPlusPlus20Specifiers.push_back(DeclSpec::getSpecifierName(TSCS));
      CPlusPlus20SpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc());
    }
    if (DS.isConstexprSpecified()) {
      BadSpecifiers.push_back("constexpr");
      BadSpecifierLocs.push_back(DS.getConstexprSpecLoc());
    }
    if (DS.isInlineSpecified()) {
      BadSpecifiers.push_back("inline");
      BadSpecifierLocs.push_back(DS.getInlineSpecLoc());
    }
    if (!BadSpecifiers.empty()) {
      auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec);
      Err << (int)BadSpecifiers.size()
          << llvm::join(BadSpecifiers.begin(), BadSpecifiers.end(), " ");
      // Don't add FixItHints to remove the specifiers; we do still respect
      // them when building the underlying variable.
      for (auto Loc : BadSpecifierLocs)
        Err << SourceRange(Loc, Loc);
    } else if (!CPlusPlus20Specifiers.empty()) {
      auto &&Warn = Diag(CPlusPlus20SpecifierLocs.front(),
                         getLangOpts().CPlusPlus2a
                             ? diag::warn_cxx17_compat_decomp_decl_spec
                             : diag::ext_decomp_decl_spec);
      Warn << (int)CPlusPlus20Specifiers.size()
           << llvm::join(CPlusPlus20Specifiers.begin(),
                         CPlusPlus20Specifiers.end(), " ");
      for (auto Loc : CPlusPlus20SpecifierLocs)
        Warn << SourceRange(Loc, Loc);
    }
    // We can't recover from it being declared as a typedef.
    if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef)
      return nullptr;
  }

  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
  QualType R = TInfo->getType();

  if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
                                      UPPC_DeclarationType))
    D.setInvalidType();

  // The syntax only allows a single ref-qualifier prior to the decomposition
  // declarator. No other declarator chunks are permitted. Also check the type
  // specifier here.
  if (DS.getTypeSpecType() != DeclSpec::TST_auto ||
      D.hasGroupingParens() || D.getNumTypeObjects() > 1 ||
      (D.getNumTypeObjects() == 1 &&
       D.getTypeObject(0).Kind != DeclaratorChunk::Reference)) {
    Diag(Decomp.getLSquareLoc(),
         (D.hasGroupingParens() ||
          (D.getNumTypeObjects() &&
           D.getTypeObject(0).Kind == DeclaratorChunk::Paren))
             ? diag::err_decomp_decl_parens
             : diag::err_decomp_decl_type)
        << R;

    // In most cases, there's no actual problem with an explicitly-specified
    // type, but a function type won't work here, and ActOnVariableDeclarator
    // shouldn't be called for such a type.
    if (R->isFunctionType())
      D.setInvalidType();
  }

  // Build the BindingDecls.
  SmallVector<BindingDecl*, 8> Bindings;

  // Build the BindingDecls.
  for (auto &B : D.getDecompositionDeclarator().bindings()) {
    // Check for name conflicts.
    DeclarationNameInfo NameInfo(B.Name, B.NameLoc);
    LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
                          ForVisibleRedeclaration);
    LookupName(Previous, S,
               /*CreateBuiltins*/DC->getRedeclContext()->isTranslationUnit());

    // It's not permitted to shadow a template parameter name.
    if (Previous.isSingleResult() &&
        Previous.getFoundDecl()->isTemplateParameter()) {
      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
                                      Previous.getFoundDecl());
      Previous.clear();
    }

    bool ConsiderLinkage = DC->isFunctionOrMethod() &&
                           DS.getStorageClassSpec() == DeclSpec::SCS_extern;
    FilterLookupForScope(Previous, DC, S, ConsiderLinkage,
                         /*AllowInlineNamespace*/false);
    if (!Previous.empty()) {
      auto *Old = Previous.getRepresentativeDecl();
      Diag(B.NameLoc, diag::err_redefinition) << B.Name;
      Diag(Old->getLocation(), diag::note_previous_definition);
    }

    auto *BD = BindingDecl::Create(Context, DC, B.NameLoc, B.Name);
    PushOnScopeChains(BD, S, true);
    Bindings.push_back(BD);
    ParsingInitForAutoVars.insert(BD);
  }

  // There are no prior lookup results for the variable itself, because it
  // is unnamed.
  DeclarationNameInfo NameInfo((IdentifierInfo *)nullptr,
                               Decomp.getLSquareLoc());
  LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
                        ForVisibleRedeclaration);

  // Build the variable that holds the non-decomposed object.
  bool AddToScope = true;
  NamedDecl *New =
      ActOnVariableDeclarator(S, D, DC, TInfo, Previous,
                              MultiTemplateParamsArg(), AddToScope, Bindings);
  if (AddToScope) {
    S->AddDecl(New);
    CurContext->addHiddenDecl(New);
  }

  if (isInOpenMPDeclareTargetContext())
    checkDeclIsAllowedInOpenMPTarget(nullptr, New);

  return New;
}

static bool checkSimpleDecomposition(
    Sema &S, ArrayRef<BindingDecl *> Bindings, ValueDecl *Src,
    QualType DecompType, const llvm::APSInt &NumElems, QualType ElemType,
    llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) {
  if ((int64_t)Bindings.size() != NumElems) {
    S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
        << DecompType << (unsigned)Bindings.size() << NumElems.toString(10)
        << (NumElems < Bindings.size());
    return true;
  }

  unsigned I = 0;
  for (auto *B : Bindings) {
    SourceLocation Loc = B->getLocation();
    ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
    if (E.isInvalid())
      return true;
    E = GetInit(Loc, E.get(), I++);
    if (E.isInvalid())
      return true;
    B->setBinding(ElemType, E.get());
  }

  return false;
}

static bool checkArrayLikeDecomposition(Sema &S,
                                        ArrayRef<BindingDecl *> Bindings,
                                        ValueDecl *Src, QualType DecompType,
                                        const llvm::APSInt &NumElems,
                                        QualType ElemType) {
  return checkSimpleDecomposition(
      S, Bindings, Src, DecompType, NumElems, ElemType,
      [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult {
        ExprResult E = S.ActOnIntegerConstant(Loc, I);
        if (E.isInvalid())
          return ExprError();
        return S.CreateBuiltinArraySubscriptExpr(Base, Loc, E.get(), Loc);
      });
}

static bool checkArrayDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
                                    ValueDecl *Src, QualType DecompType,
                                    const ConstantArrayType *CAT) {
  return checkArrayLikeDecomposition(S, Bindings, Src, DecompType,
                                     llvm::APSInt(CAT->getSize()),
                                     CAT->getElementType());
}

static bool checkVectorDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
                                     ValueDecl *Src, QualType DecompType,
                                     const VectorType *VT) {
  return checkArrayLikeDecomposition(
      S, Bindings, Src, DecompType, llvm::APSInt::get(VT->getNumElements()),
      S.Context.getQualifiedType(VT->getElementType(),
                                 DecompType.getQualifiers()));
}

static bool checkComplexDecomposition(Sema &S,
                                      ArrayRef<BindingDecl *> Bindings,
                                      ValueDecl *Src, QualType DecompType,
                                      const ComplexType *CT) {
  return checkSimpleDecomposition(
      S, Bindings, Src, DecompType, llvm::APSInt::get(2),
      S.Context.getQualifiedType(CT->getElementType(),
                                 DecompType.getQualifiers()),
      [&](SourceLocation Loc, Expr *Base, unsigned I) -> ExprResult {
        return S.CreateBuiltinUnaryOp(Loc, I ? UO_Imag : UO_Real, Base);
      });
}

static std::string printTemplateArgs(const PrintingPolicy &PrintingPolicy,
                                     TemplateArgumentListInfo &Args) {
  SmallString<128> SS;
  llvm::raw_svector_ostream OS(SS);
  bool First = true;
  for (auto &Arg : Args.arguments()) {
    if (!First)
      OS << ", ";
    Arg.getArgument().print(PrintingPolicy, OS);
    First = false;
  }
  return OS.str();
}

static bool lookupStdTypeTraitMember(Sema &S, LookupResult &TraitMemberLookup,
                                     SourceLocation Loc, StringRef Trait,
                                     TemplateArgumentListInfo &Args,
                                     unsigned DiagID) {
  auto DiagnoseMissing = [&] {
    if (DiagID)
      S.Diag(Loc, DiagID) << printTemplateArgs(S.Context.getPrintingPolicy(),
                                               Args);
    return true;
  };

  // FIXME: Factor out duplication with lookupPromiseType in SemaCoroutine.
  NamespaceDecl *Std = S.getStdNamespace();
  if (!Std)
    return DiagnoseMissing();

  // Look up the trait itself, within namespace std. We can diagnose various
  // problems with this lookup even if we've been asked to not diagnose a
  // missing specialization, because this can only fail if the user has been
  // declaring their own names in namespace std or we don't support the
  // standard library implementation in use.
  LookupResult Result(S, &S.PP.getIdentifierTable().get(Trait),
                      Loc, Sema::LookupOrdinaryName);
  if (!S.LookupQualifiedName(Result, Std))
    return DiagnoseMissing();
  if (Result.isAmbiguous())
    return true;

  ClassTemplateDecl *TraitTD = Result.getAsSingle<ClassTemplateDecl>();
  if (!TraitTD) {
    Result.suppressDiagnostics();
    NamedDecl *Found = *Result.begin();
    S.Diag(Loc, diag::err_std_type_trait_not_class_template) << Trait;
    S.Diag(Found->getLocation(), diag::note_declared_at);
    return true;
  }

  // Build the template-id.
  QualType TraitTy = S.CheckTemplateIdType(TemplateName(TraitTD), Loc, Args);
  if (TraitTy.isNull())
    return true;
  if (!S.isCompleteType(Loc, TraitTy)) {
    if (DiagID)
      S.RequireCompleteType(
          Loc, TraitTy, DiagID,
          printTemplateArgs(S.Context.getPrintingPolicy(), Args));
    return true;
  }

  CXXRecordDecl *RD = TraitTy->getAsCXXRecordDecl();
  assert(RD && "specialization of class template is not a class?");

  // Look up the member of the trait type.
  S.LookupQualifiedName(TraitMemberLookup, RD);
  return TraitMemberLookup.isAmbiguous();
}

static TemplateArgumentLoc
getTrivialIntegralTemplateArgument(Sema &S, SourceLocation Loc, QualType T,
                                   uint64_t I) {
  TemplateArgument Arg(S.Context, S.Context.MakeIntValue(I, T), T);
  return S.getTrivialTemplateArgumentLoc(Arg, T, Loc);
}

static TemplateArgumentLoc
getTrivialTypeTemplateArgument(Sema &S, SourceLocation Loc, QualType T) {
  return S.getTrivialTemplateArgumentLoc(TemplateArgument(T), QualType(), Loc);
}

namespace { enum class IsTupleLike { TupleLike, NotTupleLike, Error }; }

static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T,
                               llvm::APSInt &Size) {
  EnterExpressionEvaluationContext ContextRAII(
      S, Sema::ExpressionEvaluationContext::ConstantEvaluated);

  DeclarationName Value = S.PP.getIdentifierInfo("value");
  LookupResult R(S, Value, Loc, Sema::LookupOrdinaryName);

  // Form template argument list for tuple_size<T>.
  TemplateArgumentListInfo Args(Loc, Loc);
  Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T));

  // If there's no tuple_size specialization, it's not tuple-like.
  if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/0))
    return IsTupleLike::NotTupleLike;

  // If we get this far, we've committed to the tuple interpretation, but
  // we can still fail if there actually isn't a usable ::value.

  struct ICEDiagnoser : Sema::VerifyICEDiagnoser {
    LookupResult &R;
    TemplateArgumentListInfo &Args;
    ICEDiagnoser(LookupResult &R, TemplateArgumentListInfo &Args)
        : R(R), Args(Args) {}
    void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
      S.Diag(Loc, diag::err_decomp_decl_std_tuple_size_not_constant)
          << printTemplateArgs(S.Context.getPrintingPolicy(), Args);
    }
  } Diagnoser(R, Args);

  if (R.empty()) {
    Diagnoser.diagnoseNotICE(S, Loc, SourceRange());
    return IsTupleLike::Error;
  }

  ExprResult E =
      S.BuildDeclarationNameExpr(CXXScopeSpec(), R, /*NeedsADL*/false);
  if (E.isInvalid())
    return IsTupleLike::Error;

  E = S.VerifyIntegerConstantExpression(E.get(), &Size, Diagnoser, false);
  if (E.isInvalid())
    return IsTupleLike::Error;

  return IsTupleLike::TupleLike;
}

/// \return std::tuple_element<I, T>::type.
static QualType getTupleLikeElementType(Sema &S, SourceLocation Loc,
                                        unsigned I, QualType T) {
  // Form template argument list for tuple_element<I, T>.
  TemplateArgumentListInfo Args(Loc, Loc);
  Args.addArgument(
      getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I));
  Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T));

  DeclarationName TypeDN = S.PP.getIdentifierInfo("type");
  LookupResult R(S, TypeDN, Loc, Sema::LookupOrdinaryName);
  if (lookupStdTypeTraitMember(
          S, R, Loc, "tuple_element", Args,
          diag::err_decomp_decl_std_tuple_element_not_specialized))
    return QualType();

  auto *TD = R.getAsSingle<TypeDecl>();
  if (!TD) {
    R.suppressDiagnostics();
    S.Diag(Loc, diag::err_decomp_decl_std_tuple_element_not_specialized)
      << printTemplateArgs(S.Context.getPrintingPolicy(), Args);
    if (!R.empty())
      S.Diag(R.getRepresentativeDecl()->getLocation(), diag::note_declared_at);
    return QualType();
  }

  return S.Context.getTypeDeclType(TD);
}

namespace {
struct BindingDiagnosticTrap {
  Sema &S;
  DiagnosticErrorTrap Trap;
  BindingDecl *BD;

  BindingDiagnosticTrap(Sema &S, BindingDecl *BD)
      : S(S), Trap(S.Diags), BD(BD) {}
  ~BindingDiagnosticTrap() {
    if (Trap.hasErrorOccurred())
      S.Diag(BD->getLocation(), diag::note_in_binding_decl_init) << BD;
  }
};
}

static bool checkTupleLikeDecomposition(Sema &S,
                                        ArrayRef<BindingDecl *> Bindings,
                                        VarDecl *Src, QualType DecompType,
                                        const llvm::APSInt &TupleSize) {
  if ((int64_t)Bindings.size() != TupleSize) {
    S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
        << DecompType << (unsigned)Bindings.size() << TupleSize.toString(10)
        << (TupleSize < Bindings.size());
    return true;
  }

  if (Bindings.empty())
    return false;

  DeclarationName GetDN = S.PP.getIdentifierInfo("get");

  // [dcl.decomp]p3:
  //   The unqualified-id get is looked up in the scope of E by class member
  //   access lookup ...
  LookupResult MemberGet(S, GetDN, Src->getLocation(), Sema::LookupMemberName);
  bool UseMemberGet = false;
  if (S.isCompleteType(Src->getLocation(), DecompType)) {
    if (auto *RD = DecompType->getAsCXXRecordDecl())
      S.LookupQualifiedName(MemberGet, RD);
    if (MemberGet.isAmbiguous())
      return true;
    //   ... and if that finds at least one declaration that is a function
    //   template whose first template parameter is a non-type parameter ...
    for (NamedDecl *D : MemberGet) {
      if (FunctionTemplateDecl *FTD =
              dyn_cast<FunctionTemplateDecl>(D->getUnderlyingDecl())) {
        TemplateParameterList *TPL = FTD->getTemplateParameters();
        if (TPL->size() != 0 &&
            isa<NonTypeTemplateParmDecl>(TPL->getParam(0))) {
          //   ... the initializer is e.get<i>().
          UseMemberGet = true;
          break;
        }
      }
    }
  }

  unsigned I = 0;
  for (auto *B : Bindings) {
    BindingDiagnosticTrap Trap(S, B);
    SourceLocation Loc = B->getLocation();

    ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
    if (E.isInvalid())
      return true;

    //   e is an lvalue if the type of the entity is an lvalue reference and
    //   an xvalue otherwise
    if (!Src->getType()->isLValueReferenceType())
      E = ImplicitCastExpr::Create(S.Context, E.get()->getType(), CK_NoOp,
                                   E.get(), nullptr, VK_XValue);

    TemplateArgumentListInfo Args(Loc, Loc);
    Args.addArgument(
        getTrivialIntegralTemplateArgument(S, Loc, S.Context.getSizeType(), I));

    if (UseMemberGet) {
      //   if [lookup of member get] finds at least one declaration, the
      //   initializer is e.get<i-1>().
      E = S.BuildMemberReferenceExpr(E.get(), DecompType, Loc, false,
                                     CXXScopeSpec(), SourceLocation(), nullptr,
                                     MemberGet, &Args, nullptr);
      if (E.isInvalid())
        return true;

      E = S.BuildCallExpr(nullptr, E.get(), Loc, None, Loc);
    } else {
      //   Otherwise, the initializer is get<i-1>(e), where get is looked up
      //   in the associated namespaces.
      Expr *Get = UnresolvedLookupExpr::Create(
          S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(),
          DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/true, &Args,
          UnresolvedSetIterator(), UnresolvedSetIterator());

      Expr *Arg = E.get();
      E = S.BuildCallExpr(nullptr, Get, Loc, Arg, Loc);
    }
    if (E.isInvalid())
      return true;
    Expr *Init = E.get();

    //   Given the type T designated by std::tuple_element<i - 1, E>::type,
    QualType T = getTupleLikeElementType(S, Loc, I, DecompType);
    if (T.isNull())
      return true;

    //   each vi is a variable of type "reference to T" initialized with the
    //   initializer, where the reference is an lvalue reference if the
    //   initializer is an lvalue and an rvalue reference otherwise
    QualType RefType =
        S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName());
    if (RefType.isNull())
      return true;
    auto *RefVD = VarDecl::Create(
        S.Context, Src->getDeclContext(), Loc, Loc,
        B->getDeclName().getAsIdentifierInfo(), RefType,
        S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass());
    RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
    RefVD->setTSCSpec(Src->getTSCSpec());
    RefVD->setImplicit();
    if (Src->isInlineSpecified())
      RefVD->setInlineSpecified();
    RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD);

    InitializedEntity Entity = InitializedEntity::InitializeBinding(RefVD);
    InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc);
    InitializationSequence Seq(S, Entity, Kind, Init);
    E = Seq.Perform(S, Entity, Kind, Init);
    if (E.isInvalid())
      return true;
    E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false);
    if (E.isInvalid())
      return true;
    RefVD->setInit(E.get());
    RefVD->checkInitIsICE();

    E = S.BuildDeclarationNameExpr(CXXScopeSpec(),
                                   DeclarationNameInfo(B->getDeclName(), Loc),
                                   RefVD);
    if (E.isInvalid())
      return true;

    B->setBinding(T, E.get());
    I++;
  }

  return false;
}

/// Find the base class to decompose in a built-in decomposition of a class type.
/// This base class search is, unfortunately, not quite like any other that we
/// perform anywhere else in C++.
static DeclAccessPair findDecomposableBaseClass(Sema &S, SourceLocation Loc,
                                                const CXXRecordDecl *RD,
                                                CXXCastPath &BasePath) {
  auto BaseHasFields = [](const CXXBaseSpecifier *Specifier,
                          CXXBasePath &Path) {
    return Specifier->getType()->getAsCXXRecordDecl()->hasDirectFields();
  };

  const CXXRecordDecl *ClassWithFields = nullptr;
  AccessSpecifier AS = AS_public;
  if (RD->hasDirectFields())
    // [dcl.decomp]p4:
    //   Otherwise, all of E's non-static data members shall be public direct
    //   members of E ...
    ClassWithFields = RD;
  else {
    //   ... or of ...
    CXXBasePaths Paths;
    Paths.setOrigin(const_cast<CXXRecordDecl*>(RD));
    if (!RD->lookupInBases(BaseHasFields, Paths)) {
      // If no classes have fields, just decompose RD itself. (This will work
      // if and only if zero bindings were provided.)
      return DeclAccessPair::make(const_cast<CXXRecordDecl*>(RD), AS_public);
    }

    CXXBasePath *BestPath = nullptr;
    for (auto &P : Paths) {
      if (!BestPath)
        BestPath = &P;
      else if (!S.Context.hasSameType(P.back().Base->getType(),
                                      BestPath->back().Base->getType())) {
        //   ... the same ...
        S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members)
          << false << RD << BestPath->back().Base->getType()
          << P.back().Base->getType();
        return DeclAccessPair();
      } else if (P.Access < BestPath->Access) {
        BestPath = &P;
      }
    }

    //   ... unambiguous ...
    QualType BaseType = BestPath->back().Base->getType();
    if (Paths.isAmbiguous(S.Context.getCanonicalType(BaseType))) {
      S.Diag(Loc, diag::err_decomp_decl_ambiguous_base)
        << RD << BaseType << S.getAmbiguousPathsDisplayString(Paths);
      return DeclAccessPair();
    }

    //   ... [accessible, implied by other rules] base class of E.
    S.CheckBaseClassAccess(Loc, BaseType, S.Context.getRecordType(RD),
                           *BestPath, diag::err_decomp_decl_inaccessible_base);
    AS = BestPath->Access;

    ClassWithFields = BaseType->getAsCXXRecordDecl();
    S.BuildBasePathArray(Paths, BasePath);
  }

  // The above search did not check whether the selected class itself has base
  // classes with fields, so check that now.
  CXXBasePaths Paths;
  if (ClassWithFields->lookupInBases(BaseHasFields, Paths)) {
    S.Diag(Loc, diag::err_decomp_decl_multiple_bases_with_members)
      << (ClassWithFields == RD) << RD << ClassWithFields
      << Paths.front().back().Base->getType();
    return DeclAccessPair();
  }

  return DeclAccessPair::make(const_cast<CXXRecordDecl*>(ClassWithFields), AS);
}

static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
                                     ValueDecl *Src, QualType DecompType,
                                     const CXXRecordDecl *OrigRD) {
  if (S.RequireCompleteType(Src->getLocation(), DecompType,
                            diag::err_incomplete_type))
    return true;

  CXXCastPath BasePath;
  DeclAccessPair BasePair =
      findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath);
  const CXXRecordDecl *RD = cast_or_null<CXXRecordDecl>(BasePair.getDecl());
  if (!RD)
    return true;
  QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD),
                                                 DecompType.getQualifiers());

  auto DiagnoseBadNumberOfBindings = [&]() -> bool {
    unsigned NumFields =
        std::count_if(RD->field_begin(), RD->field_end(),
                      [](FieldDecl *FD) { return !FD->isUnnamedBitfield(); });
    assert(Bindings.size() != NumFields);
    S.Diag(Src->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
        << DecompType << (unsigned)Bindings.size() << NumFields
        << (NumFields < Bindings.size());
    return true;
  };

  //   all of E's non-static data members shall be [...] well-formed
  //   when named as e.name in the context of the structured binding,
  //   E shall not have an anonymous union member, ...
  unsigned I = 0;
  for (auto *FD : RD->fields()) {
    if (FD->isUnnamedBitfield())
      continue;

    if (FD->isAnonymousStructOrUnion()) {
      S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
        << DecompType << FD->getType()->isUnionType();
      S.Diag(FD->getLocation(), diag::note_declared_at);
      return true;
    }

    // We have a real field to bind.
    if (I >= Bindings.size())
      return DiagnoseBadNumberOfBindings();
    auto *B = Bindings[I++];
    SourceLocation Loc = B->getLocation();

    // The field must be accessible in the context of the structured binding.
    // We already checked that the base class is accessible.
    // FIXME: Add 'const' to AccessedEntity's classes so we can remove the
    // const_cast here.
    S.CheckStructuredBindingMemberAccess(
        Loc, const_cast<CXXRecordDecl *>(OrigRD),
        DeclAccessPair::make(FD, CXXRecordDecl::MergeAccess(
                                     BasePair.getAccess(), FD->getAccess())));

    // Initialize the binding to Src.FD.
    ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
    if (E.isInvalid())
      return true;
    E = S.ImpCastExprToType(E.get(), BaseType, CK_UncheckedDerivedToBase,
                            VK_LValue, &BasePath);
    if (E.isInvalid())
      return true;
    E = S.BuildFieldReferenceExpr(E.get(), /*IsArrow*/ false, Loc,
                                  CXXScopeSpec(), FD,
                                  DeclAccessPair::make(FD, FD->getAccess()),
                                  DeclarationNameInfo(FD->getDeclName(), Loc));
    if (E.isInvalid())
      return true;

    // If the type of the member is T, the referenced type is cv T, where cv is
    // the cv-qualification of the decomposition expression.
    //
    // FIXME: We resolve a defect here: if the field is mutable, we do not add
    // 'const' to the type of the field.
    Qualifiers Q = DecompType.getQualifiers();
    if (FD->isMutable())
      Q.removeConst();
    B->setBinding(S.BuildQualifiedType(FD->getType(), Loc, Q), E.get());
  }

  if (I != Bindings.size())
    return DiagnoseBadNumberOfBindings();

  return false;
}

void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) {
  QualType DecompType = DD->getType();

  // If the type of the decomposition is dependent, then so is the type of
  // each binding.
  if (DecompType->isDependentType()) {
    for (auto *B : DD->bindings())
      B->setType(Context.DependentTy);
    return;
  }

  DecompType = DecompType.getNonReferenceType();
  ArrayRef<BindingDecl*> Bindings = DD->bindings();

  // C++1z [dcl.decomp]/2:
  //   If E is an array type [...]
  // As an extension, we also support decomposition of built-in complex and
  // vector types.
  if (auto *CAT = Context.getAsConstantArrayType(DecompType)) {
    if (checkArrayDecomposition(*this, Bindings, DD, DecompType, CAT))
      DD->setInvalidDecl();
    return;
  }
  if (auto *VT = DecompType->getAs<VectorType>()) {
    if (checkVectorDecomposition(*this, Bindings, DD, DecompType, VT))
      DD->setInvalidDecl();
    return;
  }
  if (auto *CT = DecompType->getAs<ComplexType>()) {
    if (checkComplexDecomposition(*this, Bindings, DD, DecompType, CT))
      DD->setInvalidDecl();
    return;
  }

  // C++1z [dcl.decomp]/3:
  //   if the expression std::tuple_size<E>::value is a well-formed integral
  //   constant expression, [...]
  llvm::APSInt TupleSize(32);
  switch (isTupleLike(*this, DD->getLocation(), DecompType, TupleSize)) {
  case IsTupleLike::Error:
    DD->setInvalidDecl();
    return;

  case IsTupleLike::TupleLike:
    if (checkTupleLikeDecomposition(*this, Bindings, DD, DecompType, TupleSize))
      DD->setInvalidDecl();
    return;

  case IsTupleLike::NotTupleLike:
    break;
  }

  // C++1z [dcl.dcl]/8:
  //   [E shall be of array or non-union class type]
  CXXRecordDecl *RD = DecompType->getAsCXXRecordDecl();
  if (!RD || RD->isUnion()) {
    Diag(DD->getLocation(), diag::err_decomp_decl_unbindable_type)
        << DD << !RD << DecompType;
    DD->setInvalidDecl();
    return;
  }

  // C++1z [dcl.decomp]/4:
  //   all of E's non-static data members shall be [...] direct members of
  //   E or of the same unambiguous public base class of E, ...
  if (checkMemberDecomposition(*this, Bindings, DD, DecompType, RD))
    DD->setInvalidDecl();
}

/// Merge the exception specifications of two variable declarations.
///
/// This is called when there's a redeclaration of a VarDecl. The function
/// checks if the redeclaration might have an exception specification and
/// validates compatibility and merges the specs if necessary.
void Sema::MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old) {
  // Shortcut if exceptions are disabled.
  if (!getLangOpts().CXXExceptions)
    return;

  assert(Context.hasSameType(New->getType(), Old->getType()) &&
         "Should only be called if types are otherwise the same.");

  QualType NewType = New->getType();
  QualType OldType = Old->getType();

  // We're only interested in pointers and references to functions, as well
  // as pointers to member functions.
  if (const ReferenceType *R = NewType->getAs<ReferenceType>()) {
    NewType = R->getPointeeType();
    OldType = OldType->getAs<ReferenceType>()->getPointeeType();
  } else if (const PointerType *P = NewType->getAs<PointerType>()) {
    NewType = P->getPointeeType();
    OldType = OldType->getAs<PointerType>()->getPointeeType();
  } else if (const MemberPointerType *M = NewType->getAs<MemberPointerType>()) {
    NewType = M->getPointeeType();
    OldType = OldType->getAs<MemberPointerType>()->getPointeeType();
  }

  if (!NewType->isFunctionProtoType())
    return;

  // There's lots of special cases for functions. For function pointers, system
  // libraries are hopefully not as broken so that we don't need these
  // workarounds.
  if (CheckEquivalentExceptionSpec(
        OldType->getAs<FunctionProtoType>(), Old->getLocation(),
        NewType->getAs<FunctionProtoType>(), New->getLocation())) {
    New->setInvalidDecl();
  }
}

/// CheckCXXDefaultArguments - Verify that the default arguments for a
/// function declaration are well-formed according to C++
/// [dcl.fct.default].
void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
  unsigned NumParams = FD->getNumParams();
  unsigned p;

  // Find first parameter with a default argument
  for (p = 0; p < NumParams; ++p) {
    ParmVarDecl *Param = FD->getParamDecl(p);
    if (Param->hasDefaultArg())
      break;
  }

  // C++11 [dcl.fct.default]p4:
  //   In a given function declaration, each parameter subsequent to a parameter
  //   with a default argument shall have a default argument supplied in this or
  //   a previous declaration or shall be a function parameter pack. A default
  //   argument shall not be redefined by a later declaration (not even to the
  //   same value).
  unsigned LastMissingDefaultArg = 0;
  for (; p < NumParams; ++p) {
    ParmVarDecl *Param = FD->getParamDecl(p);
    if (!Param->hasDefaultArg() && !Param->isParameterPack()) {
      if (Param->isInvalidDecl())
        /* We already complained about this parameter. */;
      else if (Param->getIdentifier())
        Diag(Param->getLocation(),
             diag::err_param_default_argument_missing_name)
          << Param->getIdentifier();
      else
        Diag(Param->getLocation(),
             diag::err_param_default_argument_missing);

      LastMissingDefaultArg = p;
    }
  }

  if (LastMissingDefaultArg > 0) {
    // Some default arguments were missing. Clear out all of the
    // default arguments up to (and including) the last missing
    // default argument, so that we leave the function parameters
    // in a semantically valid state.
    for (p = 0; p <= LastMissingDefaultArg; ++p) {
      ParmVarDecl *Param = FD->getParamDecl(p);
      if (Param->hasDefaultArg()) {
        Param->setDefaultArg(nullptr);
      }
    }
  }
}

// CheckConstexprParameterTypes - Check whether a function's parameter types
// are all literal types. If so, return true. If not, produce a suitable
// diagnostic and return false.
static bool CheckConstexprParameterTypes(Sema &SemaRef,
                                         const FunctionDecl *FD) {
  unsigned ArgIndex = 0;
  const FunctionProtoType *FT = FD->getType()->getAs<FunctionProtoType>();
  for (FunctionProtoType::param_type_iterator i = FT->param_type_begin(),
                                              e = FT->param_type_end();
       i != e; ++i, ++ArgIndex) {
    const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
    SourceLocation ParamLoc = PD->getLocation();
    if (!(*i)->isDependentType() &&
        SemaRef.RequireLiteralType(ParamLoc, *i,
                                   diag::err_constexpr_non_literal_param,
                                   ArgIndex+1, PD->getSourceRange(),
                                   isa<CXXConstructorDecl>(FD)))
      return false;
  }
  return true;
}

/// Get diagnostic %select index for tag kind for
/// record diagnostic message.
/// WARNING: Indexes apply to particular diagnostics only!
///
/// \returns diagnostic %select index.
static unsigned getRecordDiagFromTagKind(TagTypeKind Tag) {
  switch (Tag) {
  case TTK_Struct: return 0;
  case TTK_Interface: return 1;
  case TTK_Class:  return 2;
  default: llvm_unreachable("Invalid tag kind for record diagnostic!");
  }
}

// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
// the requirements of a constexpr function definition or a constexpr
// constructor definition. If so, return true. If not, produce appropriate
// diagnostics and return false.
//
// This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
  const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD);
  if (MD && MD->isInstance()) {
    // C++11 [dcl.constexpr]p4:
    //  The definition of a constexpr constructor shall satisfy the following
    //  constraints:
    //  - the class shall not have any virtual base classes;
    //
    // FIXME: This only applies to constructors, not arbitrary member
    // functions.
    const CXXRecordDecl *RD = MD->getParent();
    if (RD->getNumVBases()) {
      Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
        << isa<CXXConstructorDecl>(NewFD)
        << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
      for (const auto &I : RD->vbases())
        Diag(I.getBeginLoc(), diag::note_constexpr_virtual_base_here)
            << I.getSourceRange();
      return false;
    }
  }

  if (!isa<CXXConstructorDecl>(NewFD)) {
    // C++11 [dcl.constexpr]p3:
    //  The definition of a constexpr function shall satisfy the following
    //  constraints:
    // - it shall not be virtual; (removed in C++20)
    const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD);
    if (Method && Method->isVirtual()) {
      if (getLangOpts().CPlusPlus2a) {
        Diag(Method->getLocation(), diag::warn_cxx17_compat_constexpr_virtual);
      } else {
        Method = Method->getCanonicalDecl();
        Diag(Method->getLocation(), diag::err_constexpr_virtual);

        // If it's not obvious why this function is virtual, find an overridden
        // function which uses the 'virtual' keyword.
        const CXXMethodDecl *WrittenVirtual = Method;
        while (!WrittenVirtual->isVirtualAsWritten())
          WrittenVirtual = *WrittenVirtual->begin_overridden_methods();
        if (WrittenVirtual != Method)
          Diag(WrittenVirtual->getLocation(),
               diag::note_overridden_virtual_function);
        return false;
      }
    }

    // - its return type shall be a literal type;
    QualType RT = NewFD->getReturnType();
    if (!RT->isDependentType() &&
        RequireLiteralType(NewFD->getLocation(), RT,
                           diag::err_constexpr_non_literal_return))
      return false;
  }

  // - each of its parameter types shall be a literal type;
  if (!CheckConstexprParameterTypes(*this, NewFD))
    return false;

  return true;
}

/// Check the given declaration statement is legal within a constexpr function
/// body. C++11 [dcl.constexpr]p3,p4, and C++1y [dcl.constexpr]p3.
///
/// \return true if the body is OK (maybe only as an extension), false if we
///         have diagnosed a problem.
static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl,
                                   DeclStmt *DS, SourceLocation &Cxx1yLoc) {
  // C++11 [dcl.constexpr]p3 and p4:
  //  The definition of a constexpr function(p3) or constructor(p4) [...] shall
  //  contain only
  for (const auto *DclIt : DS->decls()) {
    switch (DclIt->getKind()) {
    case Decl::StaticAssert:
    case Decl::Using:
    case Decl::UsingShadow:
    case Decl::UsingDirective:
    case Decl::UnresolvedUsingTypename:
    case Decl::UnresolvedUsingValue:
      //   - static_assert-declarations
      //   - using-declarations,
      //   - using-directives,
      continue;

    case Decl::Typedef:
    case Decl::TypeAlias: {
      //   - typedef declarations and alias-declarations that do not define
      //     classes or enumerations,
      const auto *TN = cast<TypedefNameDecl>(DclIt);
      if (TN->getUnderlyingType()->isVariablyModifiedType()) {
        // Don't allow variably-modified types in constexpr functions.
        TypeLoc TL = TN->getTypeSourceInfo()->getTypeLoc();
        SemaRef.Diag(TL.getBeginLoc(), diag::err_constexpr_vla)
          << TL.getSourceRange() << TL.getType()
          << isa<CXXConstructorDecl>(Dcl);
        return false;
      }
      continue;
    }

    case Decl::Enum:
    case Decl::CXXRecord:
      // C++1y allows types to be defined, not just declared.
      if (cast<TagDecl>(DclIt)->isThisDeclarationADefinition())
        SemaRef.Diag(DS->getBeginLoc(),
                     SemaRef.getLangOpts().CPlusPlus14
                         ? diag::warn_cxx11_compat_constexpr_type_definition
                         : diag::ext_constexpr_type_definition)
            << isa<CXXConstructorDecl>(Dcl);
      continue;

    case Decl::EnumConstant:
    case Decl::IndirectField:
    case Decl::ParmVar:
      // These can only appear with other declarations which are banned in
      // C++11 and permitted in C++1y, so ignore them.
      continue;

    case Decl::Var:
    case Decl::Decomposition: {
      // C++1y [dcl.constexpr]p3 allows anything except:
      //   a definition of a variable of non-literal type or of static or
      //   thread storage duration or for which no initialization is performed.
      const auto *VD = cast<VarDecl>(DclIt);
      if (VD->isThisDeclarationADefinition()) {
        if (VD->isStaticLocal()) {
          SemaRef.Diag(VD->getLocation(),
                       diag::err_constexpr_local_var_static)
            << isa<CXXConstructorDecl>(Dcl)
            << (VD->getTLSKind() == VarDecl::TLS_Dynamic);
          return false;
        }
        if (!VD->getType()->isDependentType() &&
            SemaRef.RequireLiteralType(
              VD->getLocation(), VD->getType(),
              diag::err_constexpr_local_var_non_literal_type,
              isa<CXXConstructorDecl>(Dcl)))
          return false;
        if (!VD->getType()->isDependentType() &&
            !VD->hasInit() && !VD->isCXXForRangeDecl()) {
          SemaRef.Diag(VD->getLocation(),
                       diag::err_constexpr_local_var_no_init)
            << isa<CXXConstructorDecl>(Dcl);
          return false;
        }
      }
      SemaRef.Diag(VD->getLocation(),
                   SemaRef.getLangOpts().CPlusPlus14
                    ? diag::warn_cxx11_compat_constexpr_local_var
                    : diag::ext_constexpr_local_var)
        << isa<CXXConstructorDecl>(Dcl);
      continue;
    }

    case Decl::NamespaceAlias:
    case Decl::Function:
      // These are disallowed in C++11 and permitted in C++1y. Allow them
      // everywhere as an extension.
      if (!Cxx1yLoc.isValid())
        Cxx1yLoc = DS->getBeginLoc();
      continue;

    default:
      SemaRef.Diag(DS->getBeginLoc(), diag::err_constexpr_body_invalid_stmt)
          << isa<CXXConstructorDecl>(Dcl);
      return false;
    }
  }

  return true;
}

/// Check that the given field is initialized within a constexpr constructor.
///
/// \param Dcl The constexpr constructor being checked.
/// \param Field The field being checked. This may be a member of an anonymous
///        struct or union nested within the class being checked.
/// \param Inits All declarations, including anonymous struct/union members and
///        indirect members, for which any initialization was provided.
/// \param Diagnosed Set to true if an error is produced.
static void CheckConstexprCtorInitializer(Sema &SemaRef,
                                          const FunctionDecl *Dcl,
                                          FieldDecl *Field,
                                          llvm::SmallSet<Decl*, 16> &Inits,
                                          bool &Diagnosed) {
  if (Field->isInvalidDecl())
    return;

  if (Field->isUnnamedBitfield())
    return;

  // Anonymous unions with no variant members and empty anonymous structs do not
  // need to be explicitly initialized. FIXME: Anonymous structs that contain no
  // indirect fields don't need initializing.
  if (Field->isAnonymousStructOrUnion() &&
      (Field->getType()->isUnionType()
           ? !Field->getType()->getAsCXXRecordDecl()->hasVariantMembers()
           : Field->getType()->getAsCXXRecordDecl()->isEmpty()))
    return;

  if (!Inits.count(Field)) {
    if (!Diagnosed) {
      SemaRef.Diag(Dcl->getLocation(), diag::err_constexpr_ctor_missing_init);
      Diagnosed = true;
    }
    SemaRef.Diag(Field->getLocation(), diag::note_constexpr_ctor_missing_init);
  } else if (Field->isAnonymousStructOrUnion()) {
    const RecordDecl *RD = Field->getType()->castAs<RecordType>()->getDecl();
    for (auto *I : RD->fields())
      // If an anonymous union contains an anonymous struct of which any member
      // is initialized, all members must be initialized.
      if (!RD->isUnion() || Inits.count(I))
        CheckConstexprCtorInitializer(SemaRef, Dcl, I, Inits, Diagnosed);
  }
}

/// Check the provided statement is allowed in a constexpr function
/// definition.
static bool
CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S,
                           SmallVectorImpl<SourceLocation> &ReturnStmts,
                           SourceLocation &Cxx1yLoc, SourceLocation &Cxx2aLoc) {
  // - its function-body shall be [...] a compound-statement that contains only
  switch (S->getStmtClass()) {
  case Stmt::NullStmtClass:
    //   - null statements,
    return true;

  case Stmt::DeclStmtClass:
    //   - static_assert-declarations
    //   - using-declarations,
    //   - using-directives,
    //   - typedef declarations and alias-declarations that do not define
    //     classes or enumerations,
    if (!CheckConstexprDeclStmt(SemaRef, Dcl, cast<DeclStmt>(S), Cxx1yLoc))
      return false;
    return true;

  case Stmt::ReturnStmtClass:
    //   - and exactly one return statement;
    if (isa<CXXConstructorDecl>(Dcl)) {
      // C++1y allows return statements in constexpr constructors.
      if (!Cxx1yLoc.isValid())
        Cxx1yLoc = S->getBeginLoc();
      return true;
    }

    ReturnStmts.push_back(S->getBeginLoc());
    return true;

  case Stmt::CompoundStmtClass: {
    // C++1y allows compound-statements.
    if (!Cxx1yLoc.isValid())
      Cxx1yLoc = S->getBeginLoc();

    CompoundStmt *CompStmt = cast<CompoundStmt>(S);
    for (auto *BodyIt : CompStmt->body()) {
      if (!CheckConstexprFunctionStmt(SemaRef, Dcl, BodyIt, ReturnStmts,
                                      Cxx1yLoc, Cxx2aLoc))
        return false;
    }
    return true;
  }

  case Stmt::AttributedStmtClass:
    if (!Cxx1yLoc.isValid())
      Cxx1yLoc = S->getBeginLoc();
    return true;

  case Stmt::IfStmtClass: {
    // C++1y allows if-statements.
    if (!Cxx1yLoc.isValid())
      Cxx1yLoc = S->getBeginLoc();

    IfStmt *If = cast<IfStmt>(S);
    if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts,
                                    Cxx1yLoc, Cxx2aLoc))
      return false;
    if (If->getElse() &&
        !CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts,
                                    Cxx1yLoc, Cxx2aLoc))
      return false;
    return true;
  }

  case Stmt::WhileStmtClass:
  case Stmt::DoStmtClass:
  case Stmt::ForStmtClass:
  case Stmt::CXXForRangeStmtClass:
  case Stmt::ContinueStmtClass:
    // C++1y allows all of these. We don't allow them as extensions in C++11,
    // because they don't make sense without variable mutation.
    if (!SemaRef.getLangOpts().CPlusPlus14)
      break;
    if (!Cxx1yLoc.isValid())
      Cxx1yLoc = S->getBeginLoc();
    for (Stmt *SubStmt : S->children())
      if (SubStmt &&
          !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
                                      Cxx1yLoc, Cxx2aLoc))
        return false;
    return true;

  case Stmt::SwitchStmtClass:
  case Stmt::CaseStmtClass:
  case Stmt::DefaultStmtClass:
  case Stmt::BreakStmtClass:
    // C++1y allows switch-statements, and since they don't need variable
    // mutation, we can reasonably allow them in C++11 as an extension.
    if (!Cxx1yLoc.isValid())
      Cxx1yLoc = S->getBeginLoc();
    for (Stmt *SubStmt : S->children())
      if (SubStmt &&
          !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
                                      Cxx1yLoc, Cxx2aLoc))
        return false;
    return true;

  case Stmt::CXXTryStmtClass:
    if (Cxx2aLoc.isInvalid())
      Cxx2aLoc = S->getBeginLoc();
    for (Stmt *SubStmt : S->children()) {
      if (SubStmt &&
          !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
                                      Cxx1yLoc, Cxx2aLoc))
        return false;
    }
    return true;

  case Stmt::CXXCatchStmtClass:
    // Do not bother checking the language mode (already covered by the
    // try block check).
    if (!CheckConstexprFunctionStmt(SemaRef, Dcl,
                                    cast<CXXCatchStmt>(S)->getHandlerBlock(),
                                    ReturnStmts, Cxx1yLoc, Cxx2aLoc))
      return false;
    return true;

  default:
    if (!isa<Expr>(S))
      break;

    // C++1y allows expression-statements.
    if (!Cxx1yLoc.isValid())
      Cxx1yLoc = S->getBeginLoc();
    return true;
  }

  SemaRef.Diag(S->getBeginLoc(), diag::err_constexpr_body_invalid_stmt)
      << isa<CXXConstructorDecl>(Dcl);
  return false;
}

/// Check the body for the given constexpr function declaration only contains
/// the permitted types of statement. C++11 [dcl.constexpr]p3,p4.
///
/// \return true if the body is OK, false if we have diagnosed a problem.
bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
  SmallVector<SourceLocation, 4> ReturnStmts;

  if (isa<CXXTryStmt>(Body)) {
    // C++11 [dcl.constexpr]p3:
    //  The definition of a constexpr function shall satisfy the following
    //  constraints: [...]
    // - its function-body shall be = delete, = default, or a
    //   compound-statement
    //
    // C++11 [dcl.constexpr]p4:
    //  In the definition of a constexpr constructor, [...]
    // - its function-body shall not be a function-try-block;
    //
    // This restriction is lifted in C++2a, as long as inner statements also
    // apply the general constexpr rules.
    Diag(Body->getBeginLoc(),
         !getLangOpts().CPlusPlus2a
             ? diag::ext_constexpr_function_try_block_cxx2a
             : diag::warn_cxx17_compat_constexpr_function_try_block)
        << isa<CXXConstructorDecl>(Dcl);
  }

  // - its function-body shall be [...] a compound-statement that contains only
  //   [... list of cases ...]
  //
  // Note that walking the children here is enough to properly check for
  // CompoundStmt and CXXTryStmt body.
  SourceLocation Cxx1yLoc, Cxx2aLoc;
  for (Stmt *SubStmt : Body->children()) {
    if (SubStmt &&
        !CheckConstexprFunctionStmt(*this, Dcl, SubStmt, ReturnStmts,
                                    Cxx1yLoc, Cxx2aLoc))
      return false;
  }

  if (Cxx2aLoc.isValid())
    Diag(Cxx2aLoc,
         getLangOpts().CPlusPlus2a
           ? diag::warn_cxx17_compat_constexpr_body_invalid_stmt
           : diag::ext_constexpr_body_invalid_stmt_cxx2a)
      << isa<CXXConstructorDecl>(Dcl);
  if (Cxx1yLoc.isValid())
    Diag(Cxx1yLoc,
         getLangOpts().CPlusPlus14
           ? diag::warn_cxx11_compat_constexpr_body_invalid_stmt
           : diag::ext_constexpr_body_invalid_stmt)
      << isa<CXXConstructorDecl>(Dcl);

  if (const CXXConstructorDecl *Constructor
        = dyn_cast<CXXConstructorDecl>(Dcl)) {
    const CXXRecordDecl *RD = Constructor->getParent();
    // DR1359:
    // - every non-variant non-static data member and base class sub-object
    //   shall be initialized;
    // DR1460:
    // - if the class is a union having variant members, exactly one of them
    //   shall be initialized;
    if (RD->isUnion()) {
      if (Constructor->getNumCtorInitializers() == 0 &&
          RD->hasVariantMembers()) {
        Diag(Dcl->getLocation(), diag::err_constexpr_union_ctor_no_init);
        return false;
      }
    } else if (!Constructor->isDependentContext() &&
               !Constructor->isDelegatingConstructor()) {
      assert(RD->getNumVBases() == 0 && "constexpr ctor with virtual bases");

      // Skip detailed checking if we have enough initializers, and we would
      // allow at most one initializer per member.
      bool AnyAnonStructUnionMembers = false;
      unsigned Fields = 0;
      for (CXXRecordDecl::field_iterator I = RD->field_begin(),
           E = RD->field_end(); I != E; ++I, ++Fields) {
        if (I->isAnonymousStructOrUnion()) {
          AnyAnonStructUnionMembers = true;
          break;
        }
      }
      // DR1460:
      // - if the class is a union-like class, but is not a union, for each of
      //   its anonymous union members having variant members, exactly one of
      //   them shall be initialized;
      if (AnyAnonStructUnionMembers ||
          Constructor->getNumCtorInitializers() != RD->getNumBases() + Fields) {
        // Check initialization of non-static data members. Base classes are
        // always initialized so do not need to be checked. Dependent bases
        // might not have initializers in the member initializer list.
        llvm::SmallSet<Decl*, 16> Inits;
        for (const auto *I: Constructor->inits()) {
          if (FieldDecl *FD = I->getMember())
            Inits.insert(FD);
          else if (IndirectFieldDecl *ID = I->getIndirectMember())
            Inits.insert(ID->chain_begin(), ID->chain_end());
        }

        bool Diagnosed = false;
        for (auto *I : RD->fields())
          CheckConstexprCtorInitializer(*this, Dcl, I, Inits, Diagnosed);
        if (Diagnosed)
          return false;
      }
    }
  } else {
    if (ReturnStmts.empty()) {
      // C++1y doesn't require constexpr functions to contain a 'return'
      // statement. We still do, unless the return type might be void, because
      // otherwise if there's no return statement, the function cannot
      // be used in a core constant expression.
      bool OK = getLangOpts().CPlusPlus14 &&
                (Dcl->getReturnType()->isVoidType() ||
                 Dcl->getReturnType()->isDependentType());
      Diag(Dcl->getLocation(),
           OK ? diag::warn_cxx11_compat_constexpr_body_no_return
              : diag::err_constexpr_body_no_return);
      if (!OK)
        return false;
    } else if (ReturnStmts.size() > 1) {
      Diag(ReturnStmts.back(),
           getLangOpts().CPlusPlus14
             ? diag::warn_cxx11_compat_constexpr_body_multiple_return
             : diag::ext_constexpr_body_multiple_return);
      for (unsigned I = 0; I < ReturnStmts.size() - 1; ++I)
        Diag(ReturnStmts[I], diag::note_constexpr_body_previous_return);
    }
  }

  // C++11 [dcl.constexpr]p5:
  //   if no function argument values exist such that the function invocation
  //   substitution would produce a constant expression, the program is
  //   ill-formed; no diagnostic required.
  // C++11 [dcl.constexpr]p3:
  //   - every constructor call and implicit conversion used in initializing the
  //     return value shall be one of those allowed in a constant expression.
  // C++11 [dcl.constexpr]p4:
  //   - every constructor involved in initializing non-static data members and
  //     base class sub-objects shall be a constexpr constructor.
  SmallVector<PartialDiagnosticAt, 8> Diags;
  if (!Expr::isPotentialConstantExpr(Dcl, Diags)) {
    Diag(Dcl->getLocation(), diag::ext_constexpr_function_never_constant_expr)
      << isa<CXXConstructorDecl>(Dcl);
    for (size_t I = 0, N = Diags.size(); I != N; ++I)
      Diag(Diags[I].first, Diags[I].second);
    // Don't return false here: we allow this for compatibility in
    // system headers.
  }

  return true;
}

/// Get the class that is directly named by the current context. This is the
/// class for which an unqualified-id in this scope could name a constructor
/// or destructor.
///
/// If the scope specifier denotes a class, this will be that class.
/// If the scope specifier is empty, this will be the class whose
/// member-specification we are currently within. Otherwise, there
/// is no such class.
CXXRecordDecl *Sema::getCurrentClass(Scope *, const CXXScopeSpec *SS) {
  assert(getLangOpts().CPlusPlus && "No class names in C!");

  if (SS && SS->isInvalid())
    return nullptr;

  if (SS && SS->isNotEmpty()) {
    DeclContext *DC = computeDeclContext(*SS, true);
    return dyn_cast_or_null<CXXRecordDecl>(DC);
  }

  return dyn_cast_or_null<CXXRecordDecl>(CurContext);
}

/// isCurrentClassName - Determine whether the identifier II is the
/// name of the class type currently being defined. In the case of
/// nested classes, this will only return true if II is the name of
/// the innermost class.
bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *S,
                              const CXXScopeSpec *SS) {
  CXXRecordDecl *CurDecl = getCurrentClass(S, SS);
  return CurDecl && &II == CurDecl->getIdentifier();
}

/// Determine whether the identifier II is a typo for the name of
/// the class type currently being defined. If so, update it to the identifier
/// that should have been used.
bool Sema::isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS) {
  assert(getLangOpts().CPlusPlus && "No class names in C!");

  if (!getLangOpts().SpellChecking)
    return false;

  CXXRecordDecl *CurDecl;
  if (SS && SS->isSet() && !SS->isInvalid()) {
    DeclContext *DC = computeDeclContext(*SS, true);
    CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
  } else
    CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);

  if (CurDecl && CurDecl->getIdentifier() && II != CurDecl->getIdentifier() &&
      3 * II->getName().edit_distance(CurDecl->getIdentifier()->getName())
          < II->getLength()) {
    II = CurDecl->getIdentifier();
    return true;
  }

  return false;
}

/// Determine whether the given class is a base class of the given
/// class, including looking at dependent bases.
static bool findCircularInheritance(const CXXRecordDecl *Class,
                                    const CXXRecordDecl *Current) {
  SmallVector<const CXXRecordDecl*, 8> Queue;

  Class = Class->getCanonicalDecl();
  while (true) {
    for (const auto &I : Current->bases()) {
      CXXRecordDecl *Base = I.getType()->getAsCXXRecordDecl();
      if (!Base)
        continue;

      Base = Base->getDefinition();
      if (!Base)
        continue;

      if (Base->getCanonicalDecl() == Class)
        return true;

      Queue.push_back(Base);
    }

    if (Queue.empty())
      return false;

    Current = Queue.pop_back_val();
  }

  return false;
}

/// Check the validity of a C++ base class specifier.
///
/// \returns a new CXXBaseSpecifier if well-formed, emits diagnostics
/// and returns NULL otherwise.
CXXBaseSpecifier *
Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
                         SourceRange SpecifierRange,
                         bool Virtual, AccessSpecifier Access,
                         TypeSourceInfo *TInfo,
                         SourceLocation EllipsisLoc) {
  QualType BaseType = TInfo->getType();

  // C++ [class.union]p1:
  //   A union shall not have base classes.
  if (Class->isUnion()) {
    Diag(Class->getLocation(), diag::err_base_clause_on_union)
      << SpecifierRange;
    return nullptr;
  }

  if (EllipsisLoc.isValid() &&
      !TInfo->getType()->containsUnexpandedParameterPack()) {
    Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
      << TInfo->getTypeLoc().getSourceRange();
    EllipsisLoc = SourceLocation();
  }

  SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc();

  if (BaseType->isDependentType()) {
    // Make sure that we don't have circular inheritance among our dependent
    // bases. For non-dependent bases, the check for completeness below handles
    // this.
    if (CXXRecordDecl *BaseDecl = BaseType->getAsCXXRecordDecl()) {
      if (BaseDecl->getCanonicalDecl() == Class->getCanonicalDecl() ||
          ((BaseDecl = BaseDecl->getDefinition()) &&
           findCircularInheritance(Class, BaseDecl))) {
        Diag(BaseLoc, diag::err_circular_inheritance)
          << BaseType << Context.getTypeDeclType(Class);

        if (BaseDecl->getCanonicalDecl() != Class->getCanonicalDecl())
          Diag(BaseDecl->getLocation(), diag::note_previous_decl)
            << BaseType;

        return nullptr;
      }
    }

    return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
                                          Class->getTagKind() == TTK_Class,
                                          Access, TInfo, EllipsisLoc);
  }

  // Base specifiers must be record types.
  if (!BaseType->isRecordType()) {
    Diag(BaseLoc, diag::err_base_must_be_class) << SpecifierRange;
    return nullptr;
  }

  // C++ [class.union]p1:
  //   A union shall not be used as a base class.
  if (BaseType->isUnionType()) {
    Diag(BaseLoc, diag::err_union_as_base_class) << SpecifierRange;
    return nullptr;
  }

  // For the MS ABI, propagate DLL attributes to base class templates.
  if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
    if (Attr *ClassAttr = getDLLAttr(Class)) {
      if (auto *BaseTemplate = dyn_cast_or_null<ClassTemplateSpecializationDecl>(
              BaseType->getAsCXXRecordDecl())) {
        propagateDLLAttrToBaseClassTemplate(Class, ClassAttr, BaseTemplate,
                                            BaseLoc);
      }
    }
  }

  // C++ [class.derived]p2:
  //   The class-name in a base-specifier shall not be an incompletely
  //   defined class.
  if (RequireCompleteType(BaseLoc, BaseType,
                          diag::err_incomplete_base_class, SpecifierRange)) {
    Class->setInvalidDecl();
    return nullptr;
  }

  // If the base class is polymorphic or isn't empty, the new one is/isn't, too.
  RecordDecl *BaseDecl = BaseType->getAs<RecordType>()->getDecl();
  assert(BaseDecl && "Record type has no declaration");
  BaseDecl = BaseDecl->getDefinition();
  assert(BaseDecl && "Base type is not incomplete, but has no definition");
  CXXRecordDecl *CXXBaseDecl = cast<CXXRecordDecl>(BaseDecl);
  assert(CXXBaseDecl && "Base type is not a C++ type");

  // Microsoft docs say:
  // "If a base-class has a code_seg attribute, derived classes must have the
  // same attribute."
  const auto *BaseCSA = CXXBaseDecl->getAttr<CodeSegAttr>();
  const auto *DerivedCSA = Class->getAttr<CodeSegAttr>();
  if ((DerivedCSA || BaseCSA) &&
      (!BaseCSA || !DerivedCSA || BaseCSA->getName() != DerivedCSA->getName())) {
    Diag(Class->getLocation(), diag::err_mismatched_code_seg_base);
    Diag(CXXBaseDecl->getLocation(), diag::note_base_class_specified_here)
      << CXXBaseDecl;
    return nullptr;
  }

  // A class which contains a flexible array member is not suitable for use as a
  // base class:
  //   - If the layout determines that a base comes before another base,
  //     the flexible array member would index into the subsequent base.
  //   - If the layout determines that base comes before the derived class,
  //     the flexible array member would index into the derived class.
  if (CXXBaseDecl->hasFlexibleArrayMember()) {
    Diag(BaseLoc, diag::err_base_class_has_flexible_array_member)
      << CXXBaseDecl->getDeclName();
    return nullptr;
  }

  // C++ [class]p3:
  //   If a class is marked final and it appears as a base-type-specifier in
  //   base-clause, the program is ill-formed.
  if (FinalAttr *FA = CXXBaseDecl->getAttr<FinalAttr>()) {
    Diag(BaseLoc, diag::err_class_marked_final_used_as_base)
      << CXXBaseDecl->getDeclName()
      << FA->isSpelledAsSealed();
    Diag(CXXBaseDecl->getLocation(), diag::note_entity_declared_at)
        << CXXBaseDecl->getDeclName() << FA->getRange();
    return nullptr;
  }

  if (BaseDecl->isInvalidDecl())
    Class->setInvalidDecl();

  // Create the base specifier.
  return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
                                        Class->getTagKind() == TTK_Class,
                                        Access, TInfo, EllipsisLoc);
}

/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
/// one entry in the base class list of a class specifier, for
/// example:
///    class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
BaseResult
Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
                         ParsedAttributes &Attributes,
                         bool Virtual, AccessSpecifier Access,
                         ParsedType basetype, SourceLocation BaseLoc,
                         SourceLocation EllipsisLoc) {
  if (!classdecl)
    return true;

  AdjustDeclIfTemplate(classdecl);
  CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(classdecl);
  if (!Class)
    return true;

  // We haven't yet attached the base specifiers.
  Class->setIsParsingBaseSpecifiers();

  // We do not support any C++11 attributes on base-specifiers yet.
  // Diagnose any attributes we see.
  for (const ParsedAttr &AL : Attributes) {
    if (AL.isInvalid() || AL.getKind() == ParsedAttr::IgnoredAttribute)
      continue;
    Diag(AL.getLoc(), AL.getKind() == ParsedAttr::UnknownAttribute
                          ? (unsigned)diag::warn_unknown_attribute_ignored
                          : (unsigned)diag::err_base_specifier_attribute)
        << AL.getName();
  }

  TypeSourceInfo *TInfo = nullptr;
  GetTypeFromParser(basetype, &TInfo);

  if (EllipsisLoc.isInvalid() &&
      DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
                                      UPPC_BaseType))
    return true;

  if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
                                                      Virtual, Access, TInfo,
                                                      EllipsisLoc))
    return BaseSpec;
  else
    Class->setInvalidDecl();

  return true;
}

/// Use small set to collect indirect bases.  As this is only used
/// locally, there's no need to abstract the small size parameter.
typedef llvm::SmallPtrSet<QualType, 4> IndirectBaseSet;

/// Recursively add the bases of Type.  Don't add Type itself.
static void
NoteIndirectBases(ASTContext &Context, IndirectBaseSet &Set,
                  const QualType &Type)
{
  // Even though the incoming type is a base, it might not be
  // a class -- it could be a template parm, for instance.
  if (auto Rec = Type->getAs<RecordType>()) {
    auto Decl = Rec->getAsCXXRecordDecl();

    // Iterate over its bases.
    for (const auto &BaseSpec : Decl->bases()) {
      QualType Base = Context.getCanonicalType(BaseSpec.getType())
        .getUnqualifiedType();
      if (Set.insert(Base).second)
        // If we've not already seen it, recurse.
        NoteIndirectBases(Context, Set, Base);
    }
  }
}

/// Performs the actual work of attaching the given base class
/// specifiers to a C++ class.
bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class,
                                MutableArrayRef<CXXBaseSpecifier *> Bases) {
 if (Bases.empty())
    return false;

  // Used to keep track of which base types we have already seen, so
  // that we can properly diagnose redundant direct base types. Note
  // that the key is always the unqualified canonical type of the base
  // class.
  std::map<QualType, CXXBaseSpecifier*, QualTypeOrdering> KnownBaseTypes;

  // Used to track indirect bases so we can see if a direct base is
  // ambiguous.
  IndirectBaseSet IndirectBaseTypes;

  // Copy non-redundant base specifiers into permanent storage.
  unsigned NumGoodBases = 0;
  bool Invalid = false;
  for (unsigned idx = 0; idx < Bases.size(); ++idx) {
    QualType NewBaseType
      = Context.getCanonicalType(Bases[idx]->getType());
    NewBaseType = NewBaseType.getLocalUnqualifiedType();

    CXXBaseSpecifier *&KnownBase = KnownBaseTypes[NewBaseType];
    if (KnownBase) {
      // C++ [class.mi]p3:
      //   A class shall not be specified as a direct base class of a
      //   derived class more than once.
      Diag(Bases[idx]->getBeginLoc(), diag::err_duplicate_base_class)
          << KnownBase->getType() << Bases[idx]->getSourceRange();

      // Delete the duplicate base class specifier; we're going to
      // overwrite its pointer later.
      Context.Deallocate(Bases[idx]);

      Invalid = true;
    } else {
      // Okay, add this new base class.
      KnownBase = Bases[idx];
      Bases[NumGoodBases++] = Bases[idx];

      // Note this base's direct & indirect bases, if there could be ambiguity.
      if (Bases.size() > 1)
        NoteIndirectBases(Context, IndirectBaseTypes, NewBaseType);

      if (const RecordType *Record = NewBaseType->getAs<RecordType>()) {
        const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
        if (Class->isInterface() &&
              (!RD->isInterfaceLike() ||
               KnownBase->getAccessSpecifier() != AS_public)) {
          // The Microsoft extension __interface does not permit bases that
          // are not themselves public interfaces.
          Diag(KnownBase->getBeginLoc(), diag::err_invalid_base_in_interface)
              << getRecordDiagFromTagKind(RD->getTagKind()) << RD
              << RD->getSourceRange();
          Invalid = true;
        }
        if (RD->hasAttr<WeakAttr>())
          Class->addAttr(WeakAttr::CreateImplicit(Context));
      }
    }
  }

  // Attach the remaining base class specifiers to the derived class.
  Class->setBases(Bases.data(), NumGoodBases);

  // Check that the only base classes that are duplicate are virtual.
  for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
    // Check whether this direct base is inaccessible due to ambiguity.
    QualType BaseType = Bases[idx]->getType();

    // Skip all dependent types in templates being used as base specifiers.
    // Checks below assume that the base specifier is a CXXRecord.
    if (BaseType->isDependentType())
      continue;

    CanQualType CanonicalBase = Context.getCanonicalType(BaseType)
      .getUnqualifiedType();

    if (IndirectBaseTypes.count(CanonicalBase)) {
      CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                         /*DetectVirtual=*/true);
      bool found
        = Class->isDerivedFrom(CanonicalBase->getAsCXXRecordDecl(), Paths);
      assert(found);
      (void)found;

      if (Paths.isAmbiguous(CanonicalBase))
        Diag(Bases[idx]->getBeginLoc(), diag::warn_inaccessible_base_class)
            << BaseType << getAmbiguousPathsDisplayString(Paths)
            << Bases[idx]->getSourceRange();
      else
        assert(Bases[idx]->isVirtual());
    }

    // Delete the base class specifier, since its data has been copied
    // into the CXXRecordDecl.
    Context.Deallocate(Bases[idx]);
  }

  return Invalid;
}

/// ActOnBaseSpecifiers - Attach the given base specifiers to the
/// class, after checking whether there are any duplicate base
/// classes.
void Sema::ActOnBaseSpecifiers(Decl *ClassDecl,
                               MutableArrayRef<CXXBaseSpecifier *> Bases) {
  if (!ClassDecl || Bases.empty())
    return;

  AdjustDeclIfTemplate(ClassDecl);
  AttachBaseSpecifiers(cast<CXXRecordDecl>(ClassDecl), Bases);
}

/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base) {
  if (!getLangOpts().CPlusPlus)
    return false;

  CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
  if (!DerivedRD)
    return false;

  CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
  if (!BaseRD)
    return false;

  // If either the base or the derived type is invalid, don't try to
  // check whether one is derived from the other.
  if (BaseRD->isInvalidDecl() || DerivedRD->isInvalidDecl())
    return false;

  // FIXME: In a modules build, do we need the entire path to be visible for us
  // to be able to use the inheritance relationship?
  if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
    return false;

  return DerivedRD->isDerivedFrom(BaseRD);
}

/// Determine whether the type \p Derived is a C++ class that is
/// derived from the type \p Base.
bool Sema::IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base,
                         CXXBasePaths &Paths) {
  if (!getLangOpts().CPlusPlus)
    return false;

  CXXRecordDecl *DerivedRD = Derived->getAsCXXRecordDecl();
  if (!DerivedRD)
    return false;

  CXXRecordDecl *BaseRD = Base->getAsCXXRecordDecl();
  if (!BaseRD)
    return false;

  if (!isCompleteType(Loc, Derived) && !DerivedRD->isBeingDefined())
    return false;

  return DerivedRD->isDerivedFrom(BaseRD, Paths);
}

static void BuildBasePathArray(const CXXBasePath &Path,
                               CXXCastPath &BasePathArray) {
  // We first go backward and check if we have a virtual base.
  // FIXME: It would be better if CXXBasePath had the base specifier for
  // the nearest virtual base.
  unsigned Start = 0;
  for (unsigned I = Path.size(); I != 0; --I) {
    if (Path[I - 1].Base->isVirtual()) {
      Start = I - 1;
      break;
    }
  }

  // Now add all bases.
  for (unsigned I = Start, E = Path.size(); I != E; ++I)
    BasePathArray.push_back(const_cast<CXXBaseSpecifier*>(Path[I].Base));
}


void Sema::BuildBasePathArray(const CXXBasePaths &Paths,
                              CXXCastPath &BasePathArray) {
  assert(BasePathArray.empty() && "Base path array must be empty!");
  assert(Paths.isRecordingPaths() && "Must record paths!");
  return ::BuildBasePathArray(Paths.front(), BasePathArray);
}
/// CheckDerivedToBaseConversion - Check whether the Derived-to-Base
/// conversion (where Derived and Base are class types) is
/// well-formed, meaning that the conversion is unambiguous (and
/// that all of the base classes are accessible). Returns true
/// and emits a diagnostic if the code is ill-formed, returns false
/// otherwise. Loc is the location where this routine should point to
/// if there is an error, and Range is the source range to highlight
/// if there is an error.
///
/// If either InaccessibleBaseID or AmbigiousBaseConvID are 0, then the
/// diagnostic for the respective type of error will be suppressed, but the
/// check for ill-formed code will still be performed.
bool
Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
                                   unsigned InaccessibleBaseID,
                                   unsigned AmbigiousBaseConvID,
                                   SourceLocation Loc, SourceRange Range,
                                   DeclarationName Name,
                                   CXXCastPath *BasePath,
                                   bool IgnoreAccess) {
  // First, determine whether the path from Derived to Base is
  // ambiguous. This is slightly more expensive than checking whether
  // the Derived to Base conversion exists, because here we need to
  // explore multiple paths to determine if there is an ambiguity.
  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                     /*DetectVirtual=*/false);
  bool DerivationOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
  if (!DerivationOkay)
    return true;

  const CXXBasePath *Path = nullptr;
  if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType()))
    Path = &Paths.front();

  // For MSVC compatibility, check if Derived directly inherits from Base. Clang
  // warns about this hierarchy under -Winaccessible-base, but MSVC allows the
  // user to access such bases.
  if (!Path && getLangOpts().MSVCCompat) {
    for (const CXXBasePath &PossiblePath : Paths) {
      if (PossiblePath.size() == 1) {
        Path = &PossiblePath;
        if (AmbigiousBaseConvID)
          Diag(Loc, diag::ext_ms_ambiguous_direct_base)
              << Base << Derived << Range;
        break;
      }
    }
  }

  if (Path) {
    if (!IgnoreAccess) {
      // Check that the base class can be accessed.
      switch (
          CheckBaseClassAccess(Loc, Base, Derived, *Path, InaccessibleBaseID)) {
      case AR_inaccessible:
        return true;
      case AR_accessible:
      case AR_dependent:
      case AR_delayed:
        break;
      }
    }

    // Build a base path if necessary.
    if (BasePath)
      ::BuildBasePathArray(*Path, *BasePath);
    return false;
  }

  if (AmbigiousBaseConvID) {
    // We know that the derived-to-base conversion is ambiguous, and
    // we're going to produce a diagnostic. Perform the derived-to-base
    // search just one more time to compute all of the possible paths so
    // that we can print them out. This is more expensive than any of
    // the previous derived-to-base checks we've done, but at this point
    // performance isn't as much of an issue.
    Paths.clear();
    Paths.setRecordingPaths(true);
    bool StillOkay = IsDerivedFrom(Loc, Derived, Base, Paths);
    assert(StillOkay && "Can only be used with a derived-to-base conversion");
    (void)StillOkay;

    // Build up a textual representation of the ambiguous paths, e.g.,
    // D -> B -> A, that will be used to illustrate the ambiguous
    // conversions in the diagnostic. We only print one of the paths
    // to each base class subobject.
    std::string PathDisplayStr = getAmbiguousPathsDisplayString(Paths);

    Diag(Loc, AmbigiousBaseConvID)
    << Derived << Base << PathDisplayStr << Range << Name;
  }
  return true;
}

bool
Sema::CheckDerivedToBaseConversion(QualType Derived, QualType Base,
                                   SourceLocation Loc, SourceRange Range,
                                   CXXCastPath *BasePath,
                                   bool IgnoreAccess) {
  return CheckDerivedToBaseConversion(
      Derived, Base, diag::err_upcast_to_inaccessible_base,
      diag::err_ambiguous_derived_to_base_conv, Loc, Range, DeclarationName(),
      BasePath, IgnoreAccess);
}


/// Builds a string representing ambiguous paths from a
/// specific derived class to different subobjects of the same base
/// class.
///
/// This function builds a string that can be used in error messages
/// to show the different paths that one can take through the
/// inheritance hierarchy to go from the derived class to different
/// subobjects of a base class. The result looks something like this:
/// @code
/// struct D -> struct B -> struct A
/// struct D -> struct C -> struct A
/// @endcode
std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) {
  std::string PathDisplayStr;
  std::set<unsigned> DisplayedPaths;
  for (CXXBasePaths::paths_iterator Path = Paths.begin();
       Path != Paths.end(); ++Path) {
    if (DisplayedPaths.insert(Path->back().SubobjectNumber).second) {
      // We haven't displayed a path to this particular base
      // class subobject yet.
      PathDisplayStr += "\n    ";
      PathDisplayStr += Context.getTypeDeclType(Paths.getOrigin()).getAsString();
      for (CXXBasePath::const_iterator Element = Path->begin();
           Element != Path->end(); ++Element)
        PathDisplayStr += " -> " + Element->Base->getType().getAsString();
    }
  }

  return PathDisplayStr;
}

//===----------------------------------------------------------------------===//
// C++ class member Handling
//===----------------------------------------------------------------------===//

/// ActOnAccessSpecifier - Parsed an access specifier followed by a colon.
bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc,
                                SourceLocation ColonLoc,
                                const ParsedAttributesView &Attrs) {
  assert(Access != AS_none && "Invalid kind for syntactic access specifier!");
  AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext,
                                                  ASLoc, ColonLoc);
  CurContext->addHiddenDecl(ASDecl);
  return ProcessAccessDeclAttributeList(ASDecl, Attrs);
}

/// CheckOverrideControl - Check C++11 override control semantics.
void Sema::CheckOverrideControl(NamedDecl *D) {
  if (D->isInvalidDecl())
    return;

  // We only care about "override" and "final" declarations.
  if (!D->hasAttr<OverrideAttr>() && !D->hasAttr<FinalAttr>())
    return;

  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);

  // We can't check dependent instance methods.
  if (MD && MD->isInstance() &&
      (MD->getParent()->hasAnyDependentBases() ||
       MD->getType()->isDependentType()))
    return;

  if (MD && !MD->isVirtual()) {
    // If we have a non-virtual method, check if if hides a virtual method.
    // (In that case, it's most likely the method has the wrong type.)
    SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
    FindHiddenVirtualMethods(MD, OverloadedMethods);

    if (!OverloadedMethods.empty()) {
      if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) {
        Diag(OA->getLocation(),
             diag::override_keyword_hides_virtual_member_function)
          << "override" << (OverloadedMethods.size() > 1);
      } else if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
        Diag(FA->getLocation(),
             diag::override_keyword_hides_virtual_member_function)
          << (FA->isSpelledAsSealed() ? "sealed" : "final")
          << (OverloadedMethods.size() > 1);
      }
      NoteHiddenVirtualMethods(MD, OverloadedMethods);
      MD->setInvalidDecl();
      return;
    }
    // Fall through into the general case diagnostic.
    // FIXME: We might want to attempt typo correction here.
  }

  if (!MD || !MD->isVirtual()) {
    if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) {
      Diag(OA->getLocation(),
           diag::override_keyword_only_allowed_on_virtual_member_functions)
        << "override" << FixItHint::CreateRemoval(OA->getLocation());
      D->dropAttr<OverrideAttr>();
    }
    if (FinalAttr *FA = D->getAttr<FinalAttr>()) {
      Diag(FA->getLocation(),
           diag::override_keyword_only_allowed_on_virtual_member_functions)
        << (FA->isSpelledAsSealed() ? "sealed" : "final")
        << FixItHint::CreateRemoval(FA->getLocation());
      D->dropAttr<FinalAttr>();
    }
    return;
  }

  // C++11 [class.virtual]p5:
  //   If a function is marked with the virt-specifier override and
  //   does not override a member function of a base class, the program is
  //   ill-formed.
  bool HasOverriddenMethods = MD->size_overridden_methods() != 0;
  if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods)
    Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding)
      << MD->getDeclName();
}

void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) {
  if (D->isInvalidDecl() || D->hasAttr<OverrideAttr>())
    return;
  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D);
  if (!MD || MD->isImplicit() || MD->hasAttr<FinalAttr>())
    return;

  SourceLocation Loc = MD->getLocation();
  SourceLocation SpellingLoc = Loc;
  if (getSourceManager().isMacroArgExpansion(Loc))
    SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).getBegin();
  SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
  if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
      return;

  if (MD->size_overridden_methods() > 0) {
    unsigned DiagID = isa<CXXDestructorDecl>(MD)
                          ? diag::warn_destructor_marked_not_override_overriding
                          : diag::warn_function_marked_not_override_overriding;
    Diag(MD->getLocation(), DiagID) << MD->getDeclName();
    const CXXMethodDecl *OMD = *MD->begin_overridden_methods();
    Diag(OMD->getLocation(), diag::note_overridden_virtual_function);
  }
}

/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member
/// function overrides a virtual member function marked 'final', according to
/// C++11 [class.virtual]p4.
bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
                                                  const CXXMethodDecl *Old) {
  FinalAttr *FA = Old->getAttr<FinalAttr>();
  if (!FA)
    return false;

  Diag(New->getLocation(), diag::err_final_function_overridden)
    << New->getDeclName()
    << FA->isSpelledAsSealed();
  Diag(Old->getLocation(), diag::note_overridden_virtual_function);
  return true;
}

static bool InitializationHasSideEffects(const FieldDecl &FD) {
  const Type *T = FD.getType()->getBaseElementTypeUnsafe();
  // FIXME: Destruction of ObjC lifetime types has side-effects.
  if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
    return !RD->isCompleteDefinition() ||
           !RD->hasTrivialDefaultConstructor() ||
           !RD->hasTrivialDestructor();
  return false;
}

static const ParsedAttr *getMSPropertyAttr(const ParsedAttributesView &list) {
  ParsedAttributesView::const_iterator Itr =
      llvm::find_if(list, [](const ParsedAttr &AL) {
        return AL.isDeclspecPropertyAttribute();
      });
  if (Itr != list.end())
    return &*Itr;
  return nullptr;
}

// Check if there is a field shadowing.
void Sema::CheckShadowInheritedFields(const SourceLocation &Loc,
                                      DeclarationName FieldName,
                                      const CXXRecordDecl *RD,
                                      bool DeclIsField) {
  if (Diags.isIgnored(diag::warn_shadow_field, Loc))
    return;

  // To record a shadowed field in a base
  std::map<CXXRecordDecl*, NamedDecl*> Bases;
  auto FieldShadowed = [&](const CXXBaseSpecifier *Specifier,
                           CXXBasePath &Path) {
    const auto Base = Specifier->getType()->getAsCXXRecordDecl();
    // Record an ambiguous path directly
    if (Bases.find(Base) != Bases.end())
      return true;
    for (const auto Field : Base->lookup(FieldName)) {
      if ((isa<FieldDecl>(Field) || isa<IndirectFieldDecl>(Field)) &&
          Field->getAccess() != AS_private) {
        assert(Field->getAccess() != AS_none);
        assert(Bases.find(Base) == Bases.end());
        Bases[Base] = Field;
        return true;
      }
    }
    return false;
  };

  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                     /*DetectVirtual=*/true);
  if (!RD->lookupInBases(FieldShadowed, Paths))
    return;

  for (const auto &P : Paths) {
    auto Base = P.back().Base->getType()->getAsCXXRecordDecl();
    auto It = Bases.find(Base);
    // Skip duplicated bases
    if (It == Bases.end())
      continue;
    auto BaseField = It->second;
    assert(BaseField->getAccess() != AS_private);
    if (AS_none !=
        CXXRecordDecl::MergeAccess(P.Access, BaseField->getAccess())) {
      Diag(Loc, diag::warn_shadow_field)
        << FieldName << RD << Base << DeclIsField;
      Diag(BaseField->getLocation(), diag::note_shadow_field);
      Bases.erase(It);
    }
  }
}

/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
/// bitfield width if there is one, 'InitExpr' specifies the initializer if
/// one has been parsed, and 'InitStyle' is set if an in-class initializer is
/// present (but parsing it has been deferred).
NamedDecl *
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
                               MultiTemplateParamsArg TemplateParameterLists,
                               Expr *BW, const VirtSpecifiers &VS,
                               InClassInitStyle InitStyle) {
  const DeclSpec &DS = D.getDeclSpec();
  DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
  DeclarationName Name = NameInfo.getName();
  SourceLocation Loc = NameInfo.getLoc();

  // For anonymous bitfields, the location should point to the type.
  if (Loc.isInvalid())
    Loc = D.getBeginLoc();

  Expr *BitWidth = static_cast<Expr*>(BW);

  assert(isa<CXXRecordDecl>(CurContext));
  assert(!DS.isFriendSpecified());

  bool isFunc = D.isDeclarationOfFunction();
  const ParsedAttr *MSPropertyAttr =
      getMSPropertyAttr(D.getDeclSpec().getAttributes());

  if (cast<CXXRecordDecl>(CurContext)->isInterface()) {
    // The Microsoft extension __interface only permits public member functions
    // and prohibits constructors, destructors, operators, non-public member
    // functions, static methods and data members.
    unsigned InvalidDecl;
    bool ShowDeclName = true;
    if (!isFunc &&
        (DS.getStorageClassSpec() == DeclSpec::SCS_typedef || MSPropertyAttr))
      InvalidDecl = 0;
    else if (!isFunc)
      InvalidDecl = 1;
    else if (AS != AS_public)
      InvalidDecl = 2;
    else if (DS.getStorageClassSpec() == DeclSpec::SCS_static)
      InvalidDecl = 3;
    else switch (Name.getNameKind()) {
      case DeclarationName::CXXConstructorName:
        InvalidDecl = 4;
        ShowDeclName = false;
        break;

      case DeclarationName::CXXDestructorName:
        InvalidDecl = 5;
        ShowDeclName = false;
        break;

      case DeclarationName::CXXOperatorName:
      case DeclarationName::CXXConversionFunctionName:
        InvalidDecl = 6;
        break;

      default:
        InvalidDecl = 0;
        break;
    }

    if (InvalidDecl) {
      if (ShowDeclName)
        Diag(Loc, diag::err_invalid_member_in_interface)
          << (InvalidDecl-1) << Name;
      else
        Diag(Loc, diag::err_invalid_member_in_interface)
          << (InvalidDecl-1) << "";
      return nullptr;
    }
  }

  // C++ 9.2p6: A member shall not be declared to have automatic storage
  // duration (auto, register) or with the extern storage-class-specifier.
  // C++ 7.1.1p8: The mutable specifier can be applied only to names of class
  // data members and cannot be applied to names declared const or static,
  // and cannot be applied to reference members.
  switch (DS.getStorageClassSpec()) {
  case DeclSpec::SCS_unspecified:
  case DeclSpec::SCS_typedef:
  case DeclSpec::SCS_static:
    break;
  case DeclSpec::SCS_mutable:
    if (isFunc) {
      Diag(DS.getStorageClassSpecLoc(), diag::err_mutable_function);

      // FIXME: It would be nicer if the keyword was ignored only for this
      // declarator. Otherwise we could get follow-up errors.
      D.getMutableDeclSpec().ClearStorageClassSpecs();
    }
    break;
  default:
    Diag(DS.getStorageClassSpecLoc(),
         diag::err_storageclass_invalid_for_member);
    D.getMutableDeclSpec().ClearStorageClassSpecs();
    break;
  }

  bool isInstField = ((DS.getStorageClassSpec() == DeclSpec::SCS_unspecified ||
                       DS.getStorageClassSpec() == DeclSpec::SCS_mutable) &&
                      !isFunc);

  if (DS.isConstexprSpecified() && isInstField) {
    SemaDiagnosticBuilder B =
        Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member);
    SourceLocation ConstexprLoc = DS.getConstexprSpecLoc();
    if (InitStyle == ICIS_NoInit) {
      B << 0 << 0;
      if (D.getDeclSpec().getTypeQualifiers() & DeclSpec::TQ_const)
        B << FixItHint::CreateRemoval(ConstexprLoc);
      else {
        B << FixItHint::CreateReplacement(ConstexprLoc, "const");
        D.getMutableDeclSpec().ClearConstexprSpec();
        const char *PrevSpec;
        unsigned DiagID;
        bool Failed = D.getMutableDeclSpec().SetTypeQual(
            DeclSpec::TQ_const, ConstexprLoc, PrevSpec, DiagID, getLangOpts());
        (void)Failed;
        assert(!Failed && "Making a constexpr member const shouldn't fail");
      }
    } else {
      B << 1;
      const char *PrevSpec;
      unsigned DiagID;
      if (D.getMutableDeclSpec().SetStorageClassSpec(
          *this, DeclSpec::SCS_static, ConstexprLoc, PrevSpec, DiagID,
          Context.getPrintingPolicy())) {
        assert(DS.getStorageClassSpec() == DeclSpec::SCS_mutable &&
               "This is the only DeclSpec that should fail to be applied");
        B << 1;
      } else {
        B << 0 << FixItHint::CreateInsertion(ConstexprLoc, "static ");
        isInstField = false;
      }
    }
  }

  NamedDecl *Member;
  if (isInstField) {
    CXXScopeSpec &SS = D.getCXXScopeSpec();

    // Data members must have identifiers for names.
    if (!Name.isIdentifier()) {
      Diag(Loc, diag::err_bad_variable_name)
        << Name;
      return nullptr;
    }

    IdentifierInfo *II = Name.getAsIdentifierInfo();

    // Member field could not be with "template" keyword.
    // So TemplateParameterLists should be empty in this case.
    if (TemplateParameterLists.size()) {
      TemplateParameterList* TemplateParams = TemplateParameterLists[0];
      if (TemplateParams->size()) {
        // There is no such thing as a member field template.
        Diag(D.getIdentifierLoc(), diag::err_template_member)
            << II
            << SourceRange(TemplateParams->getTemplateLoc(),
                TemplateParams->getRAngleLoc());
      } else {
        // There is an extraneous 'template<>' for this member.
        Diag(TemplateParams->getTemplateLoc(),
            diag::err_template_member_noparams)
            << II
            << SourceRange(TemplateParams->getTemplateLoc(),
                TemplateParams->getRAngleLoc());
      }
      return nullptr;
    }

    if (SS.isSet() && !SS.isInvalid()) {
      // The user provided a superfluous scope specifier inside a class
      // definition:
      //
      // class X {
      //   int X::member;
      // };
      if (DeclContext *DC = computeDeclContext(SS, false))
        diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(),
                                     D.getName().getKind() ==
                                         UnqualifiedIdKind::IK_TemplateId);
      else
        Diag(D.getIdentifierLoc(), diag::err_member_qualification)
          << Name << SS.getRange();

      SS.clear();
    }

    if (MSPropertyAttr) {
      Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D,
                                BitWidth, InitStyle, AS, *MSPropertyAttr);
      if (!Member)
        return nullptr;
      isInstField = false;
    } else {
      Member = HandleField(S, cast<CXXRecordDecl>(CurContext), Loc, D,
                                BitWidth, InitStyle, AS);
      if (!Member)
        return nullptr;
    }

    CheckShadowInheritedFields(Loc, Name, cast<CXXRecordDecl>(CurContext));
  } else {
    Member = HandleDeclarator(S, D, TemplateParameterLists);
    if (!Member)
      return nullptr;

    // Non-instance-fields can't have a bitfield.
    if (BitWidth) {
      if (Member->isInvalidDecl()) {
        // don't emit another diagnostic.
      } else if (isa<VarDecl>(Member) || isa<VarTemplateDecl>(Member)) {
        // C++ 9.6p3: A bit-field shall not be a static member.
        // "static member 'A' cannot be a bit-field"
        Diag(Loc, diag::err_static_not_bitfield)
          << Name << BitWidth->getSourceRange();
      } else if (isa<TypedefDecl>(Member)) {
        // "typedef member 'x' cannot be a bit-field"
        Diag(Loc, diag::err_typedef_not_bitfield)
          << Name << BitWidth->getSourceRange();
      } else {
        // A function typedef ("typedef int f(); f a;").
        // C++ 9.6p3: A bit-field shall have integral or enumeration type.
        Diag(Loc, diag::err_not_integral_type_bitfield)
          << Name << cast<ValueDecl>(Member)->getType()
          << BitWidth->getSourceRange();
      }

      BitWidth = nullptr;
      Member->setInvalidDecl();
    }

    NamedDecl *NonTemplateMember = Member;
    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
      NonTemplateMember = FunTmpl->getTemplatedDecl();
    else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
      NonTemplateMember = VarTmpl->getTemplatedDecl();

    Member->setAccess(AS);

    // If we have declared a member function template or static data member
    // template, set the access of the templated declaration as well.
    if (NonTemplateMember != Member)
      NonTemplateMember->setAccess(AS);

    // C++ [temp.deduct.guide]p3:
    //   A deduction guide [...] for a member class template [shall be
    //   declared] with the same access [as the template].
    if (auto *DG = dyn_cast<CXXDeductionGuideDecl>(NonTemplateMember)) {
      auto *TD = DG->getDeducedTemplate();
      // Access specifiers are only meaningful if both the template and the
      // deduction guide are from the same scope.
      if (AS != TD->getAccess() &&
          TD->getDeclContext()->getRedeclContext()->Equals(
              DG->getDeclContext()->getRedeclContext())) {
        Diag(DG->getBeginLoc(), diag::err_deduction_guide_wrong_access);
        Diag(TD->getBeginLoc(), diag::note_deduction_guide_template_access)
            << TD->getAccess();
        const AccessSpecDecl *LastAccessSpec = nullptr;
        for (const auto *D : cast<CXXRecordDecl>(CurContext)->decls()) {
          if (const auto *AccessSpec = dyn_cast<AccessSpecDecl>(D))
            LastAccessSpec = AccessSpec;
        }
        assert(LastAccessSpec && "differing access with no access specifier");
        Diag(LastAccessSpec->getBeginLoc(), diag::note_deduction_guide_access)
            << AS;
      }
    }
  }

  if (VS.isOverrideSpecified())
    Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context, 0));
  if (VS.isFinalSpecified())
    Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context,
                                            VS.isFinalSpelledSealed()));

  if (VS.getLastLocation().isValid()) {
    // Update the end location of a method that has a virt-specifiers.
    if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Member))
      MD->setRangeEnd(VS.getLastLocation());
  }

  CheckOverrideControl(Member);

  assert((Name || isInstField) && "No identifier for non-field ?");

  if (isInstField) {
    FieldDecl *FD = cast<FieldDecl>(Member);
    FieldCollector->Add(FD);

    if (!Diags.isIgnored(diag::warn_unused_private_field, FD->getLocation())) {
      // Remember all explicit private FieldDecls that have a name, no side
      // effects and are not part of a dependent type declaration.
      if (!FD->isImplicit() && FD->getDeclName() &&
          FD->getAccess() == AS_private &&
          !FD->hasAttr<UnusedAttr>() &&
          !FD->getParent()->isDependentContext() &&
          !InitializationHasSideEffects(*FD))
        UnusedPrivateFields.insert(FD);
    }
  }

  return Member;
}

namespace {
  class UninitializedFieldVisitor
      : public EvaluatedExprVisitor<UninitializedFieldVisitor> {
    Sema &S;
    // List of Decls to generate a warning on.  Also remove Decls that become
    // initialized.
    llvm::SmallPtrSetImpl<ValueDecl*> &Decls;
    // List of base classes of the record.  Classes are removed after their
    // initializers.
    llvm::SmallPtrSetImpl<QualType> &BaseClasses;
    // Vector of decls to be removed from the Decl set prior to visiting the
    // nodes.  These Decls may have been initialized in the prior initializer.
    llvm::SmallVector<ValueDecl*, 4> DeclsToRemove;
    // If non-null, add a note to the warning pointing back to the constructor.
    const CXXConstructorDecl *Constructor;
    // Variables to hold state when processing an initializer list.  When
    // InitList is true, special case initialization of FieldDecls matching
    // InitListFieldDecl.
    bool InitList;
    FieldDecl *InitListFieldDecl;
    llvm::SmallVector<unsigned, 4> InitFieldIndex;

  public:
    typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited;
    UninitializedFieldVisitor(Sema &S,
                              llvm::SmallPtrSetImpl<ValueDecl*> &Decls,
                              llvm::SmallPtrSetImpl<QualType> &BaseClasses)
      : Inherited(S.Context), S(S), Decls(Decls), BaseClasses(BaseClasses),
        Constructor(nullptr), InitList(false), InitListFieldDecl(nullptr) {}

    // Returns true if the use of ME is not an uninitialized use.
    bool IsInitListMemberExprInitialized(MemberExpr *ME,
                                         bool CheckReferenceOnly) {
      llvm::SmallVector<FieldDecl*, 4> Fields;
      bool ReferenceField = false;
      while (ME) {
        FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
        if (!FD)
          return false;
        Fields.push_back(FD);
        if (FD->getType()->isReferenceType())
          ReferenceField = true;
        ME = dyn_cast<MemberExpr>(ME->getBase()->IgnoreParenImpCasts());
      }

      // Binding a reference to an uninitialized field is not an
      // uninitialized use.
      if (CheckReferenceOnly && !ReferenceField)
        return true;

      llvm::SmallVector<unsigned, 4> UsedFieldIndex;
      // Discard the first field since it is the field decl that is being
      // initialized.
      for (auto I = Fields.rbegin() + 1, E = Fields.rend(); I != E; ++I) {
        UsedFieldIndex.push_back((*I)->getFieldIndex());
      }

      for (auto UsedIter = UsedFieldIndex.begin(),
                UsedEnd = UsedFieldIndex.end(),
                OrigIter = InitFieldIndex.begin(),
                OrigEnd = InitFieldIndex.end();
           UsedIter != UsedEnd && OrigIter != OrigEnd; ++UsedIter, ++OrigIter) {
        if (*UsedIter < *OrigIter)
          return true;
        if (*UsedIter > *OrigIter)
          break;
      }

      return false;
    }

    void HandleMemberExpr(MemberExpr *ME, bool CheckReferenceOnly,
                          bool AddressOf) {
      if (isa<EnumConstantDecl>(ME->getMemberDecl()))
        return;

      // FieldME is the inner-most MemberExpr that is not an anonymous struct
      // or union.
      MemberExpr *FieldME = ME;

      bool AllPODFields = FieldME->getType().isPODType(S.Context);

      Expr *Base = ME;
      while (MemberExpr *SubME =
                 dyn_cast<MemberExpr>(Base->IgnoreParenImpCasts())) {

        if (isa<VarDecl>(SubME->getMemberDecl()))
          return;

        if (FieldDecl *FD = dyn_cast<FieldDecl>(SubME->getMemberDecl()))
          if (!FD->isAnonymousStructOrUnion())
            FieldME = SubME;

        if (!FieldME->getType().isPODType(S.Context))
          AllPODFields = false;

        Base = SubME->getBase();
      }

      if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts()))
        return;

      if (AddressOf && AllPODFields)
        return;

      ValueDecl* FoundVD = FieldME->getMemberDecl();

      if (ImplicitCastExpr *BaseCast = dyn_cast<ImplicitCastExpr>(Base)) {
        while (isa<ImplicitCastExpr>(BaseCast->getSubExpr())) {
          BaseCast = cast<ImplicitCastExpr>(BaseCast->getSubExpr());
        }

        if (BaseCast->getCastKind() == CK_UncheckedDerivedToBase) {
          QualType T = BaseCast->getType();
          if (T->isPointerType() &&
              BaseClasses.count(T->getPointeeType())) {
            S.Diag(FieldME->getExprLoc(), diag::warn_base_class_is_uninit)
                << T->getPointeeType() << FoundVD;
          }
        }
      }

      if (!Decls.count(FoundVD))
        return;

      const bool IsReference = FoundVD->getType()->isReferenceType();

      if (InitList && !AddressOf && FoundVD == InitListFieldDecl) {
        // Special checking for initializer lists.
        if (IsInitListMemberExprInitialized(ME, CheckReferenceOnly)) {
          return;
        }
      } else {
        // Prevent double warnings on use of unbounded references.
        if (CheckReferenceOnly && !IsReference)
          return;
      }

      unsigned diag = IsReference
          ? diag::warn_reference_field_is_uninit
          : diag::warn_field_is_uninit;
      S.Diag(FieldME->getExprLoc(), diag) << FoundVD;
      if (Constructor)
        S.Diag(Constructor->getLocation(),
               diag::note_uninit_in_this_constructor)
          << (Constructor->isDefaultConstructor() && Constructor->isImplicit());

    }

    void HandleValue(Expr *E, bool AddressOf) {
      E = E->IgnoreParens();

      if (MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
        HandleMemberExpr(ME, false /*CheckReferenceOnly*/,
                         AddressOf /*AddressOf*/);
        return;
      }

      if (ConditionalOperator *CO = dyn_cast<ConditionalOperator>(E)) {
        Visit(CO->getCond());
        HandleValue(CO->getTrueExpr(), AddressOf);
        HandleValue(CO->getFalseExpr(), AddressOf);
        return;
      }

      if (BinaryConditionalOperator *BCO =
              dyn_cast<BinaryConditionalOperator>(E)) {
        Visit(BCO->getCond());
        HandleValue(BCO->getFalseExpr(), AddressOf);
        return;
      }

      if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E)) {
        HandleValue(OVE->getSourceExpr(), AddressOf);
        return;
      }

      if (BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
        switch (BO->getOpcode()) {
        default:
          break;
        case(BO_PtrMemD):
        case(BO_PtrMemI):
          HandleValue(BO->getLHS(), AddressOf);
          Visit(BO->getRHS());
          return;
        case(BO_Comma):
          Visit(BO->getLHS());
          HandleValue(BO->getRHS(), AddressOf);
          return;
        }
      }

      Visit(E);
    }

    void CheckInitListExpr(InitListExpr *ILE) {
      InitFieldIndex.push_back(0);
      for (auto Child : ILE->children()) {
        if (InitListExpr *SubList = dyn_cast<InitListExpr>(Child)) {
          CheckInitListExpr(SubList);
        } else {
          Visit(Child);
        }
        ++InitFieldIndex.back();
      }
      InitFieldIndex.pop_back();
    }

    void CheckInitializer(Expr *E, const CXXConstructorDecl *FieldConstructor,
                          FieldDecl *Field, const Type *BaseClass) {
      // Remove Decls that may have been initialized in the previous
      // initializer.
      for (ValueDecl* VD : DeclsToRemove)
        Decls.erase(VD);
      DeclsToRemove.clear();

      Constructor = FieldConstructor;
      InitListExpr *ILE = dyn_cast<InitListExpr>(E);

      if (ILE && Field) {
        InitList = true;
        InitListFieldDecl = Field;
        InitFieldIndex.clear();
        CheckInitListExpr(ILE);
      } else {
        InitList = false;
        Visit(E);
      }

      if (Field)
        Decls.erase(Field);
      if (BaseClass)
        BaseClasses.erase(BaseClass->getCanonicalTypeInternal());
    }

    void VisitMemberExpr(MemberExpr *ME) {
      // All uses of unbounded reference fields will warn.
      HandleMemberExpr(ME, true /*CheckReferenceOnly*/, false /*AddressOf*/);
    }

    void VisitImplicitCastExpr(ImplicitCastExpr *E) {
      if (E->getCastKind() == CK_LValueToRValue) {
        HandleValue(E->getSubExpr(), false /*AddressOf*/);
        return;
      }

      Inherited::VisitImplicitCastExpr(E);
    }

    void VisitCXXConstructExpr(CXXConstructExpr *E) {
      if (E->getConstructor()->isCopyConstructor()) {
        Expr *ArgExpr = E->getArg(0);
        if (InitListExpr *ILE = dyn_cast<InitListExpr>(ArgExpr))
          if (ILE->getNumInits() == 1)
            ArgExpr = ILE->getInit(0);
        if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
          if (ICE->getCastKind() == CK_NoOp)
            ArgExpr = ICE->getSubExpr();
        HandleValue(ArgExpr, false /*AddressOf*/);
        return;
      }
      Inherited::VisitCXXConstructExpr(E);
    }

    void VisitCXXMemberCallExpr(CXXMemberCallExpr *E) {
      Expr *Callee = E->getCallee();
      if (isa<MemberExpr>(Callee)) {
        HandleValue(Callee, false /*AddressOf*/);
        for (auto Arg : E->arguments())
          Visit(Arg);
        return;
      }

      Inherited::VisitCXXMemberCallExpr(E);
    }

    void VisitCallExpr(CallExpr *E) {
      // Treat std::move as a use.
      if (E->isCallToStdMove()) {
        HandleValue(E->getArg(0), /*AddressOf=*/false);
        return;
      }

      Inherited::VisitCallExpr(E);
    }

    void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) {
      Expr *Callee = E->getCallee();

      if (isa<UnresolvedLookupExpr>(Callee))
        return Inherited::VisitCXXOperatorCallExpr(E);

      Visit(Callee);
      for (auto Arg : E->arguments())
        HandleValue(Arg->IgnoreParenImpCasts(), false /*AddressOf*/);
    }

    void VisitBinaryOperator(BinaryOperator *E) {
      // If a field assignment is detected, remove the field from the
      // uninitiailized field set.
      if (E->getOpcode() == BO_Assign)
        if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getLHS()))
          if (FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
            if (!FD->getType()->isReferenceType())
              DeclsToRemove.push_back(FD);

      if (E->isCompoundAssignmentOp()) {
        HandleValue(E->getLHS(), false /*AddressOf*/);
        Visit(E->getRHS());
        return;
      }

      Inherited::VisitBinaryOperator(E);
    }

    void VisitUnaryOperator(UnaryOperator *E) {
      if (E->isIncrementDecrementOp()) {
        HandleValue(E->getSubExpr(), false /*AddressOf*/);
        return;
      }
      if (E->getOpcode() == UO_AddrOf) {
        if (MemberExpr *ME = dyn_cast<MemberExpr>(E->getSubExpr())) {
          HandleValue(ME->getBase(), true /*AddressOf*/);
          return;
        }
      }

      Inherited::VisitUnaryOperator(E);
    }
  };

  // Diagnose value-uses of fields to initialize themselves, e.g.
  //   foo(foo)
  // where foo is not also a parameter to the constructor.
  // Also diagnose across field uninitialized use such as
  //   x(y), y(x)
  // TODO: implement -Wuninitialized and fold this into that framework.
  static void DiagnoseUninitializedFields(
      Sema &SemaRef, const CXXConstructorDecl *Constructor) {

    if (SemaRef.getDiagnostics().isIgnored(diag::warn_field_is_uninit,
                                           Constructor->getLocation())) {
      return;
    }

    if (Constructor->isInvalidDecl())
      return;

    const CXXRecordDecl *RD = Constructor->getParent();

    if (RD->getDescribedClassTemplate())
      return;

    // Holds fields that are uninitialized.
    llvm::SmallPtrSet<ValueDecl*, 4> UninitializedFields;

    // At the beginning, all fields are uninitialized.
    for (auto *I : RD->decls()) {
      if (auto *FD = dyn_cast<FieldDecl>(I)) {
        UninitializedFields.insert(FD);
      } else if (auto *IFD = dyn_cast<IndirectFieldDecl>(I)) {
        UninitializedFields.insert(IFD->getAnonField());
      }
    }

    llvm::SmallPtrSet<QualType, 4> UninitializedBaseClasses;
    for (auto I : RD->bases())
      UninitializedBaseClasses.insert(I.getType().getCanonicalType());

    if (UninitializedFields.empty() && UninitializedBaseClasses.empty())
      return;

    UninitializedFieldVisitor UninitializedChecker(SemaRef,
                                                   UninitializedFields,
                                                   UninitializedBaseClasses);

    for (const auto *FieldInit : Constructor->inits()) {
      if (UninitializedFields.empty() && UninitializedBaseClasses.empty())
        break;

      Expr *InitExpr = FieldInit->getInit();
      if (!InitExpr)
        continue;

      if (CXXDefaultInitExpr *Default =
              dyn_cast<CXXDefaultInitExpr>(InitExpr)) {
        InitExpr = Default->getExpr();
        if (!InitExpr)
          continue;
        // In class initializers will point to the constructor.
        UninitializedChecker.CheckInitializer(InitExpr, Constructor,
                                              FieldInit->getAnyMember(),
                                              FieldInit->getBaseClass());
      } else {
        UninitializedChecker.CheckInitializer(InitExpr, nullptr,
                                              FieldInit->getAnyMember(),
                                              FieldInit->getBaseClass());
      }
    }
  }
} // namespace

/// Enter a new C++ default initializer scope. After calling this, the
/// caller must call \ref ActOnFinishCXXInClassMemberInitializer, even if
/// parsing or instantiating the initializer failed.
void Sema::ActOnStartCXXInClassMemberInitializer() {
  // Create a synthetic function scope to represent the call to the constructor
  // that notionally surrounds a use of this initializer.
  PushFunctionScope();
}

/// This is invoked after parsing an in-class initializer for a
/// non-static C++ class member, and after instantiating an in-class initializer
/// in a class template. Such actions are deferred until the class is complete.
void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D,
                                                  SourceLocation InitLoc,
                                                  Expr *InitExpr) {
  // Pop the notional constructor scope we created earlier.
  PopFunctionScopeInfo(nullptr, D);

  FieldDecl *FD = dyn_cast<FieldDecl>(D);
  assert((isa<MSPropertyDecl>(D) || FD->getInClassInitStyle() != ICIS_NoInit) &&
         "must set init style when field is created");

  if (!InitExpr) {
    D->setInvalidDecl();
    if (FD)
      FD->removeInClassInitializer();
    return;
  }

  if (DiagnoseUnexpandedParameterPack(InitExpr, UPPC_Initializer)) {
    FD->setInvalidDecl();
    FD->removeInClassInitializer();
    return;
  }

  ExprResult Init = InitExpr;
  if (!FD->getType()->isDependentType() && !InitExpr->isTypeDependent()) {
    InitializedEntity Entity =
        InitializedEntity::InitializeMemberFromDefaultMemberInitializer(FD);
    InitializationKind Kind =
        FD->getInClassInitStyle() == ICIS_ListInit
            ? InitializationKind::CreateDirectList(InitExpr->getBeginLoc(),
                                                   InitExpr->getBeginLoc(),
                                                   InitExpr->getEndLoc())
            : InitializationKind::CreateCopy(InitExpr->getBeginLoc(), InitLoc);
    InitializationSequence Seq(*this, Entity, Kind, InitExpr);
    Init = Seq.Perform(*this, Entity, Kind, InitExpr);
    if (Init.isInvalid()) {
      FD->setInvalidDecl();
      return;
    }
  }

  // C++11 [class.base.init]p7:
  //   The initialization of each base and member constitutes a
  //   full-expression.
  Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false);
  if (Init.isInvalid()) {
    FD->setInvalidDecl();
    return;
  }

  InitExpr = Init.get();

  FD->setInClassInitializer(InitExpr);
}

/// Find the direct and/or virtual base specifiers that
/// correspond to the given base type, for use in base initialization
/// within a constructor.
static bool FindBaseInitializer(Sema &SemaRef,
                                CXXRecordDecl *ClassDecl,
                                QualType BaseType,
                                const CXXBaseSpecifier *&DirectBaseSpec,
                                const CXXBaseSpecifier *&VirtualBaseSpec) {
  // First, check for a direct base class.
  DirectBaseSpec = nullptr;
  for (const auto &Base : ClassDecl->bases()) {
    if (SemaRef.Context.hasSameUnqualifiedType(BaseType, Base.getType())) {
      // We found a direct base of this type. That's what we're
      // initializing.
      DirectBaseSpec = &Base;
      break;
    }
  }

  // Check for a virtual base class.
  // FIXME: We might be able to short-circuit this if we know in advance that
  // there are no virtual bases.
  VirtualBaseSpec = nullptr;
  if (!DirectBaseSpec || !DirectBaseSpec->isVirtual()) {
    // We haven't found a base yet; search the class hierarchy for a
    // virtual base class.
    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                       /*DetectVirtual=*/false);
    if (SemaRef.IsDerivedFrom(ClassDecl->getLocation(),
                              SemaRef.Context.getTypeDeclType(ClassDecl),
                              BaseType, Paths)) {
      for (CXXBasePaths::paths_iterator Path = Paths.begin();
           Path != Paths.end(); ++Path) {
        if (Path->back().Base->isVirtual()) {
          VirtualBaseSpec = Path->back().Base;
          break;
        }
      }
    }
  }

  return DirectBaseSpec || VirtualBaseSpec;
}

/// Handle a C++ member initializer using braced-init-list syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
                          Scope *S,
                          CXXScopeSpec &SS,
                          IdentifierInfo *MemberOrBase,
                          ParsedType TemplateTypeTy,
                          const DeclSpec &DS,
                          SourceLocation IdLoc,
                          Expr *InitList,
                          SourceLocation EllipsisLoc) {
  return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
                             DS, IdLoc, InitList,
                             EllipsisLoc);
}

/// Handle a C++ member initializer using parentheses syntax.
MemInitResult
Sema::ActOnMemInitializer(Decl *ConstructorD,
                          Scope *S,
                          CXXScopeSpec &SS,
                          IdentifierInfo *MemberOrBase,
                          ParsedType TemplateTypeTy,
                          const DeclSpec &DS,
                          SourceLocation IdLoc,
                          SourceLocation LParenLoc,
                          ArrayRef<Expr *> Args,
                          SourceLocation RParenLoc,
                          SourceLocation EllipsisLoc) {
  Expr *List = ParenListExpr::Create(Context, LParenLoc, Args, RParenLoc);
  return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy,
                             DS, IdLoc, List, EllipsisLoc);
}

namespace {

// Callback to only accept typo corrections that can be a valid C++ member
// intializer: either a non-static field member or a base class.
class MemInitializerValidatorCCC final : public CorrectionCandidateCallback {
public:
  explicit MemInitializerValidatorCCC(CXXRecordDecl *ClassDecl)
      : ClassDecl(ClassDecl) {}

  bool ValidateCandidate(const TypoCorrection &candidate) override {
    if (NamedDecl *ND = candidate.getCorrectionDecl()) {
      if (FieldDecl *Member = dyn_cast<FieldDecl>(ND))
        return Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl);
      return isa<TypeDecl>(ND);
    }
    return false;
  }

  std::unique_ptr<CorrectionCandidateCallback> clone() override {
    return llvm::make_unique<MemInitializerValidatorCCC>(*this);
  }

private:
  CXXRecordDecl *ClassDecl;
};

}

ValueDecl *Sema::tryLookupCtorInitMemberDecl(CXXRecordDecl *ClassDecl,
                                             CXXScopeSpec &SS,
                                             ParsedType TemplateTypeTy,
                                             IdentifierInfo *MemberOrBase) {
  if (SS.getScopeRep() || TemplateTypeTy)
    return nullptr;
  DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
  if (Result.empty())
    return nullptr;
  ValueDecl *Member;
  if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
      (Member = dyn_cast<IndirectFieldDecl>(Result.front())))
    return Member;
  return nullptr;
}

/// Handle a C++ member initializer.
MemInitResult
Sema::BuildMemInitializer(Decl *ConstructorD,
                          Scope *S,
                          CXXScopeSpec &SS,
                          IdentifierInfo *MemberOrBase,
                          ParsedType TemplateTypeTy,
                          const DeclSpec &DS,
                          SourceLocation IdLoc,
                          Expr *Init,
                          SourceLocation EllipsisLoc) {
  ExprResult Res = CorrectDelayedTyposInExpr(Init);
  if (!Res.isUsable())
    return true;
  Init = Res.get();

  if (!ConstructorD)
    return true;

  AdjustDeclIfTemplate(ConstructorD);

  CXXConstructorDecl *Constructor
    = dyn_cast<CXXConstructorDecl>(ConstructorD);
  if (!Constructor) {
    // The user wrote a constructor initializer on a function that is
    // not a C++ constructor. Ignore the error for now, because we may
    // have more member initializers coming; we'll diagnose it just
    // once in ActOnMemInitializers.
    return true;
  }

  CXXRecordDecl *ClassDecl = Constructor->getParent();

  // C++ [class.base.init]p2:
  //   Names in a mem-initializer-id are looked up in the scope of the
  //   constructor's class and, if not found in that scope, are looked
  //   up in the scope containing the constructor's definition.
  //   [Note: if the constructor's class contains a member with the
  //   same name as a direct or virtual base class of the class, a
  //   mem-initializer-id naming the member or base class and composed
  //   of a single identifier refers to the class member. A
  //   mem-initializer-id for the hidden base class may be specified
  //   using a qualified name. ]

  // Look for a member, first.
  if (ValueDecl *Member = tryLookupCtorInitMemberDecl(
          ClassDecl, SS, TemplateTypeTy, MemberOrBase)) {
    if (EllipsisLoc.isValid())
      Diag(EllipsisLoc, diag::err_pack_expansion_member_init)
          << MemberOrBase
          << SourceRange(IdLoc, Init->getSourceRange().getEnd());

    return BuildMemberInitializer(Member, Init, IdLoc);
  }
  // It didn't name a member, so see if it names a class.
  QualType BaseType;
  TypeSourceInfo *TInfo = nullptr;

  if (TemplateTypeTy) {
    BaseType = GetTypeFromParser(TemplateTypeTy, &TInfo);
    if (BaseType.isNull())
      return true;
  } else if (DS.getTypeSpecType() == TST_decltype) {
    BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
  } else if (DS.getTypeSpecType() == TST_decltype_auto) {
    Diag(DS.getTypeSpecTypeLoc(), diag::err_decltype_auto_invalid);
    return true;
  } else {
    LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
    LookupParsedName(R, S, &SS);

    TypeDecl *TyD = R.getAsSingle<TypeDecl>();
    if (!TyD) {
      if (R.isAmbiguous()) return true;

      // We don't want access-control diagnostics here.
      R.suppressDiagnostics();

      if (SS.isSet() && isDependentScopeSpecifier(SS)) {
        bool NotUnknownSpecialization = false;
        DeclContext *DC = computeDeclContext(SS, false);
        if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(DC))
          NotUnknownSpecialization = !Record->hasAnyDependentBases();

        if (!NotUnknownSpecialization) {
          // When the scope specifier can refer to a member of an unknown
          // specialization, we take it as a type name.
          BaseType = CheckTypenameType(ETK_None, SourceLocation(),
                                       SS.getWithLocInContext(Context),
                                       *MemberOrBase, IdLoc);
          if (BaseType.isNull())
            return true;

          TInfo = Context.CreateTypeSourceInfo(BaseType);
          DependentNameTypeLoc TL =
              TInfo->getTypeLoc().castAs<DependentNameTypeLoc>();
          if (!TL.isNull()) {
            TL.setNameLoc(IdLoc);
            TL.setElaboratedKeywordLoc(SourceLocation());
            TL.setQualifierLoc(SS.getWithLocInContext(Context));
          }

          R.clear();
          R.setLookupName(MemberOrBase);
        }
      }

      // If no results were found, try to correct typos.
      TypoCorrection Corr;
      MemInitializerValidatorCCC CCC(ClassDecl);
      if (R.empty() && BaseType.isNull() &&
          (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
                              CCC, CTK_ErrorRecovery, ClassDecl))) {
        if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {
          // We have found a non-static data member with a similar
          // name to what was typed; complain and initialize that
          // member.
          diagnoseTypo(Corr,
                       PDiag(diag::err_mem_init_not_member_or_class_suggest)
                         << MemberOrBase << true);
          return BuildMemberInitializer(Member, Init, IdLoc);
        } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {
          const CXXBaseSpecifier *DirectBaseSpec;
          const CXXBaseSpecifier *VirtualBaseSpec;
          if (FindBaseInitializer(*this, ClassDecl,
                                  Context.getTypeDeclType(Type),
                                  DirectBaseSpec, VirtualBaseSpec)) {
            // We have found a direct or virtual base class with a
            // similar name to what was typed; complain and initialize
            // that base class.
            diagnoseTypo(Corr,
                         PDiag(diag::err_mem_init_not_member_or_class_suggest)
                           << MemberOrBase << false,
                         PDiag() /*Suppress note, we provide our own.*/);

            const CXXBaseSpecifier *BaseSpec = DirectBaseSpec ? DirectBaseSpec
                                                              : VirtualBaseSpec;
            Diag(BaseSpec->getBeginLoc(), diag::note_base_class_specified_here)
                << BaseSpec->getType() << BaseSpec->getSourceRange();

            TyD = Type;
          }
        }
      }

      if (!TyD && BaseType.isNull()) {
        Diag(IdLoc, diag::err_mem_init_not_member_or_class)
          << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd());
        return true;
      }
    }

    if (BaseType.isNull()) {
      BaseType = Context.getTypeDeclType(TyD);
      MarkAnyDeclReferenced(TyD->getLocation(), TyD, /*OdrUse=*/false);
      if (SS.isSet()) {
        BaseType = Context.getElaboratedType(ETK_None, SS.getScopeRep(),
                                             BaseType);
        TInfo = Context.CreateTypeSourceInfo(BaseType);
        ElaboratedTypeLoc TL = TInfo->getTypeLoc().castAs<ElaboratedTypeLoc>();
        TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(IdLoc);
        TL.setElaboratedKeywordLoc(SourceLocation());
        TL.setQualifierLoc(SS.getWithLocInContext(Context));
      }
    }
  }

  if (!TInfo)
    TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc);

  return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc);
}

MemInitResult
Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
                             SourceLocation IdLoc) {
  FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member);
  IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member);
  assert((DirectMember || IndirectMember) &&
         "Member must be a FieldDecl or IndirectFieldDecl");

  if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
    return true;

  if (Member->isInvalidDecl())
    return true;

  MultiExprArg Args;
  if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
    Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
  } else if (InitListExpr *InitList = dyn_cast<InitListExpr>(Init)) {
    Args = MultiExprArg(InitList->getInits(), InitList->getNumInits());
  } else {
    // Template instantiation doesn't reconstruct ParenListExprs for us.
    Args = Init;
  }

  SourceRange InitRange = Init->getSourceRange();

  if (Member->getType()->isDependentType() || Init->isTypeDependent()) {
    // Can't check initialization for a member of dependent type or when
    // any of the arguments are type-dependent expressions.
    DiscardCleanupsInEvaluationContext();
  } else {
    bool InitList = false;
    if (isa<InitListExpr>(Init)) {
      InitList = true;
      Args = Init;
    }

    // Initialize the member.
    InitializedEntity MemberEntity =
      DirectMember ? InitializedEntity::InitializeMember(DirectMember, nullptr)
                   : InitializedEntity::InitializeMember(IndirectMember,
                                                         nullptr);
    InitializationKind Kind =
        InitList ? InitializationKind::CreateDirectList(
                       IdLoc, Init->getBeginLoc(), Init->getEndLoc())
                 : InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(),
                                                    InitRange.getEnd());

    InitializationSequence InitSeq(*this, MemberEntity, Kind, Args);
    ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, Args,
                                            nullptr);
    if (MemberInit.isInvalid())
      return true;

    // C++11 [class.base.init]p7:
    //   The initialization of each base and member constitutes a
    //   full-expression.
    MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(),
                                     /*DiscardedValue*/ false);
    if (MemberInit.isInvalid())
      return true;

    Init = MemberInit.get();
  }

  if (DirectMember) {
    return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc,
                                            InitRange.getBegin(), Init,
                                            InitRange.getEnd());
  } else {
    return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc,
                                            InitRange.getBegin(), Init,
                                            InitRange.getEnd());
  }
}

MemInitResult
Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init,
                                 CXXRecordDecl *ClassDecl) {
  SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin();
  if (!LangOpts.CPlusPlus11)
    return Diag(NameLoc, diag::err_delegating_ctor)
      << TInfo->getTypeLoc().getLocalSourceRange();
  Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor);

  bool InitList = true;
  MultiExprArg Args = Init;
  if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
    InitList = false;
    Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
  }

  SourceRange InitRange = Init->getSourceRange();
  // Initialize the object.
  InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation(
                                     QualType(ClassDecl->getTypeForDecl(), 0));
  InitializationKind Kind =
      InitList ? InitializationKind::CreateDirectList(
                     NameLoc, Init->getBeginLoc(), Init->getEndLoc())
               : InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(),
                                                  InitRange.getEnd());
  InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args);
  ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind,
                                              Args, nullptr);
  if (DelegationInit.isInvalid())
    return true;

  assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() &&
         "Delegating constructor with no target?");

  // C++11 [class.base.init]p7:
  //   The initialization of each base and member constitutes a
  //   full-expression.
  DelegationInit = ActOnFinishFullExpr(
      DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false);
  if (DelegationInit.isInvalid())
    return true;

  // If we are in a dependent context, template instantiation will
  // perform this type-checking again. Just save the arguments that we
  // received in a ParenListExpr.
  // FIXME: This isn't quite ideal, since our ASTs don't capture all
  // of the information that we have about the base
  // initializer. However, deconstructing the ASTs is a dicey process,
  // and this approach is far more likely to get the corner cases right.
  if (CurContext->isDependentContext())
    DelegationInit = Init;

  return new (Context) CXXCtorInitializer(Context, TInfo, InitRange.getBegin(),
                                          DelegationInit.getAs<Expr>(),
                                          InitRange.getEnd());
}

MemInitResult
Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo,
                           Expr *Init, CXXRecordDecl *ClassDecl,
                           SourceLocation EllipsisLoc) {
  SourceLocation BaseLoc
    = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin();

  if (!BaseType->isDependentType() && !BaseType->isRecordType())
    return Diag(BaseLoc, diag::err_base_init_does_not_name_class)
             << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();

  // C++ [class.base.init]p2:
  //   [...] Unless the mem-initializer-id names a nonstatic data
  //   member of the constructor's class or a direct or virtual base
  //   of that class, the mem-initializer is ill-formed. A
  //   mem-initializer-list can initialize a base class using any
  //   name that denotes that base class type.
  bool Dependent = BaseType->isDependentType() || Init->isTypeDependent();

  SourceRange InitRange = Init->getSourceRange();
  if (EllipsisLoc.isValid()) {
    // This is a pack expansion.
    if (!BaseType->containsUnexpandedParameterPack())  {
      Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
        << SourceRange(BaseLoc, InitRange.getEnd());

      EllipsisLoc = SourceLocation();
    }
  } else {
    // Check for any unexpanded parameter packs.
    if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer))
      return true;

    if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer))
      return true;
  }

  // Check for direct and virtual base classes.
  const CXXBaseSpecifier *DirectBaseSpec = nullptr;
  const CXXBaseSpecifier *VirtualBaseSpec = nullptr;
  if (!Dependent) {
    if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0),
                                       BaseType))
      return BuildDelegatingInitializer(BaseTInfo, Init, ClassDecl);

    FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec,
                        VirtualBaseSpec);

    // C++ [base.class.init]p2:
    // Unless the mem-initializer-id names a nonstatic data member of the
    // constructor's class or a direct or virtual base of that class, the
    // mem-initializer is ill-formed.
    if (!DirectBaseSpec && !VirtualBaseSpec) {
      // If the class has any dependent bases, then it's possible that
      // one of those types will resolve to the same type as
      // BaseType. Therefore, just treat this as a dependent base
      // class initialization.  FIXME: Should we try to check the
      // initialization anyway? It seems odd.
      if (ClassDecl->hasAnyDependentBases())
        Dependent = true;
      else
        return Diag(BaseLoc, diag::err_not_direct_base_or_virtual)
          << BaseType << Context.getTypeDeclType(ClassDecl)
          << BaseTInfo->getTypeLoc().getLocalSourceRange();
    }
  }

  if (Dependent) {
    DiscardCleanupsInEvaluationContext();

    return new (Context) CXXCtorInitializer(Context, BaseTInfo,
                                            /*IsVirtual=*/false,
                                            InitRange.getBegin(), Init,
                                            InitRange.getEnd(), EllipsisLoc);
  }

  // C++ [base.class.init]p2:
  //   If a mem-initializer-id is ambiguous because it designates both
  //   a direct non-virtual base class and an inherited virtual base
  //   class, the mem-initializer is ill-formed.
  if (DirectBaseSpec && VirtualBaseSpec)
    return Diag(BaseLoc, diag::err_base_init_direct_and_virtual)
      << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange();

  const CXXBaseSpecifier *BaseSpec = DirectBaseSpec;
  if (!BaseSpec)
    BaseSpec = VirtualBaseSpec;

  // Initialize the base.
  bool InitList = true;
  MultiExprArg Args = Init;
  if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) {
    InitList = false;
    Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs());
  }

  InitializedEntity BaseEntity =
    InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec);
  InitializationKind Kind =
      InitList ? InitializationKind::CreateDirectList(BaseLoc)
               : InitializationKind::CreateDirect(BaseLoc, InitRange.getBegin(),
                                                  InitRange.getEnd());
  InitializationSequence InitSeq(*this, BaseEntity, Kind, Args);
  ExprResult BaseInit = InitSeq.Perform(*this, BaseEntity, Kind, Args, nullptr);
  if (BaseInit.isInvalid())
    return true;

  // C++11 [class.base.init]p7:
  //   The initialization of each base and member constitutes a
  //   full-expression.
  BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(),
                                 /*DiscardedValue*/ false);
  if (BaseInit.isInvalid())
    return true;

  // If we are in a dependent context, template instantiation will
  // perform this type-checking again. Just save the arguments that we
  // received in a ParenListExpr.
  // FIXME: This isn't quite ideal, since our ASTs don't capture all
  // of the information that we have about the base
  // initializer. However, deconstructing the ASTs is a dicey process,
  // and this approach is far more likely to get the corner cases right.
  if (CurContext->isDependentContext())
    BaseInit = Init;

  return new (Context) CXXCtorInitializer(Context, BaseTInfo,
                                          BaseSpec->isVirtual(),
                                          InitRange.getBegin(),
                                          BaseInit.getAs<Expr>(),
                                          InitRange.getEnd(), EllipsisLoc);
}

// Create a static_cast\<T&&>(expr).
static Expr *CastForMoving(Sema &SemaRef, Expr *E, QualType T = QualType()) {
  if (T.isNull()) T = E->getType();
  QualType TargetType = SemaRef.BuildReferenceType(
      T, /*SpelledAsLValue*/false, SourceLocation(), DeclarationName());
  SourceLocation ExprLoc = E->getBeginLoc();
  TypeSourceInfo *TargetLoc = SemaRef.Context.getTrivialTypeSourceInfo(
      TargetType, ExprLoc);

  return SemaRef.BuildCXXNamedCast(ExprLoc, tok::kw_static_cast, TargetLoc, E,
                                   SourceRange(ExprLoc, ExprLoc),
                                   E->getSourceRange()).get();
}

/// ImplicitInitializerKind - How an implicit base or member initializer should
/// initialize its base or member.
enum ImplicitInitializerKind {
  IIK_Default,
  IIK_Copy,
  IIK_Move,
  IIK_Inherit
};

static bool
BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
                             ImplicitInitializerKind ImplicitInitKind,
                             CXXBaseSpecifier *BaseSpec,
                             bool IsInheritedVirtualBase,
                             CXXCtorInitializer *&CXXBaseInit) {
  InitializedEntity InitEntity
    = InitializedEntity::InitializeBase(SemaRef.Context, BaseSpec,
                                        IsInheritedVirtualBase);

  ExprResult BaseInit;

  switch (ImplicitInitKind) {
  case IIK_Inherit:
  case IIK_Default: {
    InitializationKind InitKind
      = InitializationKind::CreateDefault(Constructor->getLocation());
    InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None);
    BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, None);
    break;
  }

  case IIK_Move:
  case IIK_Copy: {
    bool Moving = ImplicitInitKind == IIK_Move;
    ParmVarDecl *Param = Constructor->getParamDecl(0);
    QualType ParamType = Param->getType().getNonReferenceType();

    Expr *CopyCtorArg =
      DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
                          SourceLocation(), Param, false,
                          Constructor->getLocation(), ParamType,
                          VK_LValue, nullptr);

    SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(CopyCtorArg));

    // Cast to the base class to avoid ambiguities.
    QualType ArgTy =
      SemaRef.Context.getQualifiedType(BaseSpec->getType().getUnqualifiedType(),
                                       ParamType.getQualifiers());

    if (Moving) {
      CopyCtorArg = CastForMoving(SemaRef, CopyCtorArg);
    }

    CXXCastPath BasePath;
    BasePath.push_back(BaseSpec);
    CopyCtorArg = SemaRef.ImpCastExprToType(CopyCtorArg, ArgTy,
                                            CK_UncheckedDerivedToBase,
                                            Moving ? VK_XValue : VK_LValue,
                                            &BasePath).get();

    InitializationKind InitKind
      = InitializationKind::CreateDirect(Constructor->getLocation(),
                                         SourceLocation(), SourceLocation());
    InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, CopyCtorArg);
    BaseInit = InitSeq.Perform(SemaRef, InitEntity, InitKind, CopyCtorArg);
    break;
  }
  }

  BaseInit = SemaRef.MaybeCreateExprWithCleanups(BaseInit);
  if (BaseInit.isInvalid())
    return true;

  CXXBaseInit =
    new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
               SemaRef.Context.getTrivialTypeSourceInfo(BaseSpec->getType(),
                                                        SourceLocation()),
                                             BaseSpec->isVirtual(),
                                             SourceLocation(),
                                             BaseInit.getAs<Expr>(),
                                             SourceLocation(),
                                             SourceLocation());

  return false;
}

static bool RefersToRValueRef(Expr *MemRef) {
  ValueDecl *Referenced = cast<MemberExpr>(MemRef)->getMemberDecl();
  return Referenced->getType()->isRValueReferenceType();
}

static bool
BuildImplicitMemberInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor,
                               ImplicitInitializerKind ImplicitInitKind,
                               FieldDecl *Field, IndirectFieldDecl *Indirect,
                               CXXCtorInitializer *&CXXMemberInit) {
  if (Field->isInvalidDecl())
    return true;

  SourceLocation Loc = Constructor->getLocation();

  if (ImplicitInitKind == IIK_Copy || ImplicitInitKind == IIK_Move) {
    bool Moving = ImplicitInitKind == IIK_Move;
    ParmVarDecl *Param = Constructor->getParamDecl(0);
    QualType ParamType = Param->getType().getNonReferenceType();

    // Suppress copying zero-width bitfields.
    if (Field->isZeroLengthBitField(SemaRef.Context))
      return false;

    Expr *MemberExprBase =
      DeclRefExpr::Create(SemaRef.Context, NestedNameSpecifierLoc(),
                          SourceLocation(), Param, false,
                          Loc, ParamType, VK_LValue, nullptr);

    SemaRef.MarkDeclRefReferenced(cast<DeclRefExpr>(MemberExprBase));

    if (Moving) {
      MemberExprBase = CastForMoving(SemaRef, MemberExprBase);
    }

    // Build a reference to this field within the parameter.
    CXXScopeSpec SS;
    LookupResult MemberLookup(SemaRef, Field->getDeclName(), Loc,
                              Sema::LookupMemberName);
    MemberLookup.addDecl(Indirect ? cast<ValueDecl>(Indirect)
                                  : cast<ValueDecl>(Field), AS_public);
    MemberLookup.resolveKind();
    ExprResult CtorArg
      = SemaRef.BuildMemberReferenceExpr(MemberExprBase,
                                         ParamType, Loc,
                                         /*IsArrow=*/false,
                                         SS,
                                         /*TemplateKWLoc=*/SourceLocation(),
                                         /*FirstQualifierInScope=*/nullptr,
                                         MemberLookup,
                                         /*TemplateArgs=*/nullptr,
                                         /*S*/nullptr);
    if (CtorArg.isInvalid())
      return true;

    // C++11 [class.copy]p15:
    //   - if a member m has rvalue reference type T&&, it is direct-initialized
    //     with static_cast<T&&>(x.m);
    if (RefersToRValueRef(CtorArg.get())) {
      CtorArg = CastForMoving(SemaRef, CtorArg.get());
    }

    InitializedEntity Entity =
        Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr,
                                                       /*Implicit*/ true)
                 : InitializedEntity::InitializeMember(Field, nullptr,
                                                       /*Implicit*/ true);

    // Direct-initialize to use the copy constructor.
    InitializationKind InitKind =
      InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());

    Expr *CtorArgE = CtorArg.getAs<Expr>();
    InitializationSequence InitSeq(SemaRef, Entity, InitKind, CtorArgE);
    ExprResult MemberInit =
        InitSeq.Perform(SemaRef, Entity, InitKind, MultiExprArg(&CtorArgE, 1));
    MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
    if (MemberInit.isInvalid())
      return true;

    if (Indirect)
      CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(
          SemaRef.Context, Indirect, Loc, Loc, MemberInit.getAs<Expr>(), Loc);
    else
      CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(
          SemaRef.Context, Field, Loc, Loc, MemberInit.getAs<Expr>(), Loc);
    return false;
  }

  assert((ImplicitInitKind == IIK_Default || ImplicitInitKind == IIK_Inherit) &&
         "Unhandled implicit init kind!");

  QualType FieldBaseElementType =
    SemaRef.Context.getBaseElementType(Field->getType());

  if (FieldBaseElementType->isRecordType()) {
    InitializedEntity InitEntity =
        Indirect ? InitializedEntity::InitializeMember(Indirect, nullptr,
                                                       /*Implicit*/ true)
                 : InitializedEntity::InitializeMember(Field, nullptr,
                                                       /*Implicit*/ true);
    InitializationKind InitKind =
      InitializationKind::CreateDefault(Loc);

    InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, None);
    ExprResult MemberInit =
      InitSeq.Perform(SemaRef, InitEntity, InitKind, None);

    MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
    if (MemberInit.isInvalid())
      return true;

    if (Indirect)
      CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
                                                               Indirect, Loc,
                                                               Loc,
                                                               MemberInit.get(),
                                                               Loc);
    else
      CXXMemberInit = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context,
                                                               Field, Loc, Loc,
                                                               MemberInit.get(),
                                                               Loc);
    return false;
  }

  if (!Field->getParent()->isUnion()) {
    if (FieldBaseElementType->isReferenceType()) {
      SemaRef.Diag(Constructor->getLocation(),
                   diag::err_uninitialized_member_in_ctor)
      << (int)Constructor->isImplicit()
      << SemaRef.Context.getTagDeclType(Constructor->getParent())
      << 0 << Field->getDeclName();
      SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
      return true;
    }

    if (FieldBaseElementType.isConstQualified()) {
      SemaRef.Diag(Constructor->getLocation(),
                   diag::err_uninitialized_member_in_ctor)
      << (int)Constructor->isImplicit()
      << SemaRef.Context.getTagDeclType(Constructor->getParent())
      << 1 << Field->getDeclName();
      SemaRef.Diag(Field->getLocation(), diag::note_declared_at);
      return true;
    }
  }

  if (FieldBaseElementType.hasNonTrivialObjCLifetime()) {
    // ARC and Weak:
    //   Default-initialize Objective-C pointers to NULL.
    CXXMemberInit
      = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Field,
                                                 Loc, Loc,
                 new (SemaRef.Context) ImplicitValueInitExpr(Field->getType()),
                                                 Loc);
    return false;
  }

  // Nothing to initialize.
  CXXMemberInit = nullptr;
  return false;
}

namespace {
struct BaseAndFieldInfo {
  Sema &S;
  CXXConstructorDecl *Ctor;
  bool AnyErrorsInInits;
  ImplicitInitializerKind IIK;
  llvm::DenseMap<const void *, CXXCtorInitializer*> AllBaseFields;
  SmallVector<CXXCtorInitializer*, 8> AllToInit;
  llvm::DenseMap<TagDecl*, FieldDecl*> ActiveUnionMember;

  BaseAndFieldInfo(Sema &S, CXXConstructorDecl *Ctor, bool ErrorsInInits)
    : S(S), Ctor(Ctor), AnyErrorsInInits(ErrorsInInits) {
    bool Generated = Ctor->isImplicit() || Ctor->isDefaulted();
    if (Ctor->getInheritedConstructor())
      IIK = IIK_Inherit;
    else if (Generated && Ctor->isCopyConstructor())
      IIK = IIK_Copy;
    else if (Generated && Ctor->isMoveConstructor())
      IIK = IIK_Move;
    else
      IIK = IIK_Default;
  }

  bool isImplicitCopyOrMove() const {
    switch (IIK) {
    case IIK_Copy:
    case IIK_Move:
      return true;

    case IIK_Default:
    case IIK_Inherit:
      return false;
    }

    llvm_unreachable("Invalid ImplicitInitializerKind!");
  }

  bool addFieldInitializer(CXXCtorInitializer *Init) {
    AllToInit.push_back(Init);

    // Check whether this initializer makes the field "used".
    if (Init->getInit()->HasSideEffects(S.Context))
      S.UnusedPrivateFields.remove(Init->getAnyMember());

    return false;
  }

  bool isInactiveUnionMember(FieldDecl *Field) {
    RecordDecl *Record = Field->getParent();
    if (!Record->isUnion())
      return false;

    if (FieldDecl *Active =
            ActiveUnionMember.lookup(Record->getCanonicalDecl()))
      return Active != Field->getCanonicalDecl();

    // In an implicit copy or move constructor, ignore any in-class initializer.
    if (isImplicitCopyOrMove())
      return true;

    // If there's no explicit initialization, the field is active only if it
    // has an in-class initializer...
    if (Field->hasInClassInitializer())
      return false;
    // ... or it's an anonymous struct or union whose class has an in-class
    // initializer.
    if (!Field->isAnonymousStructOrUnion())
      return true;
    CXXRecordDecl *FieldRD = Field->getType()->getAsCXXRecordDecl();
    return !FieldRD->hasInClassInitializer();
  }

  /// Determine whether the given field is, or is within, a union member
  /// that is inactive (because there was an initializer given for a different
  /// member of the union, or because the union was not initialized at all).
  bool isWithinInactiveUnionMember(FieldDecl *Field,
                                   IndirectFieldDecl *Indirect) {
    if (!Indirect)
      return isInactiveUnionMember(Field);

    for (auto *C : Indirect->chain()) {
      FieldDecl *Field = dyn_cast<FieldDecl>(C);
      if (Field && isInactiveUnionMember(Field))
        return true;
    }
    return false;
  }
};
}

/// Determine whether the given type is an incomplete or zero-lenfgth
/// array type.
static bool isIncompleteOrZeroLengthArrayType(ASTContext &Context, QualType T) {
  if (T->isIncompleteArrayType())
    return true;

  while (const ConstantArrayType *ArrayT = Context.getAsConstantArrayType(T)) {
    if (!ArrayT->getSize())
      return true;

    T = ArrayT->getElementType();
  }

  return false;
}

static bool CollectFieldInitializer(Sema &SemaRef, BaseAndFieldInfo &Info,
                                    FieldDecl *Field,
                                    IndirectFieldDecl *Indirect = nullptr) {
  if (Field->isInvalidDecl())
    return false;

  // Overwhelmingly common case: we have a direct initializer for this field.
  if (CXXCtorInitializer *Init =
          Info.AllBaseFields.lookup(Field->getCanonicalDecl()))
    return Info.addFieldInitializer(Init);

  // C++11 [class.base.init]p8:
  //   if the entity is a non-static data member that has a
  //   brace-or-equal-initializer and either
  //   -- the constructor's class is a union and no other variant member of that
  //      union is designated by a mem-initializer-id or
  //   -- the constructor's class is not a union, and, if the entity is a member
  //      of an anonymous union, no other member of that union is designated by
  //      a mem-initializer-id,
  //   the entity is initialized as specified in [dcl.init].
  //
  // We also apply the same rules to handle anonymous structs within anonymous
  // unions.
  if (Info.isWithinInactiveUnionMember(Field, Indirect))
    return false;

  if (Field->hasInClassInitializer() && !Info.isImplicitCopyOrMove()) {
    ExprResult DIE =
        SemaRef.BuildCXXDefaultInitExpr(Info.Ctor->getLocation(), Field);
    if (DIE.isInvalid())
      return true;

    auto Entity = InitializedEntity::InitializeMember(Field, nullptr, true);
    SemaRef.checkInitializerLifetime(Entity, DIE.get());

    CXXCtorInitializer *Init;
    if (Indirect)
      Init = new (SemaRef.Context)
          CXXCtorInitializer(SemaRef.Context, Indirect, SourceLocation(),
                             SourceLocation(), DIE.get(), SourceLocation());
    else
      Init = new (SemaRef.Context)
          CXXCtorInitializer(SemaRef.Context, Field, SourceLocation(),
                             SourceLocation(), DIE.get(), SourceLocation());
    return Info.addFieldInitializer(Init);
  }

  // Don't initialize incomplete or zero-length arrays.
  if (isIncompleteOrZeroLengthArrayType(SemaRef.Context, Field->getType()))
    return false;

  // Don't try to build an implicit initializer if there were semantic
  // errors in any of the initializers (and therefore we might be
  // missing some that the user actually wrote).
  if (Info.AnyErrorsInInits)
    return false;

  CXXCtorInitializer *Init = nullptr;
  if (BuildImplicitMemberInitializer(Info.S, Info.Ctor, Info.IIK, Field,
                                     Indirect, Init))
    return true;

  if (!Init)
    return false;

  return Info.addFieldInitializer(Init);
}

bool
Sema::SetDelegatingInitializer(CXXConstructorDecl *Constructor,
                               CXXCtorInitializer *Initializer) {
  assert(Initializer->isDelegatingInitializer());
  Constructor->setNumCtorInitializers(1);
  CXXCtorInitializer **initializer =
    new (Context) CXXCtorInitializer*[1];
  memcpy(initializer, &Initializer, sizeof (CXXCtorInitializer*));
  Constructor->setCtorInitializers(initializer);

  if (CXXDestructorDecl *Dtor = LookupDestructor(Constructor->getParent())) {
    MarkFunctionReferenced(Initializer->getSourceLocation(), Dtor);
    DiagnoseUseOfDecl(Dtor, Initializer->getSourceLocation());
  }

  DelegatingCtorDecls.push_back(Constructor);

  DiagnoseUninitializedFields(*this, Constructor);

  return false;
}

bool Sema::SetCtorInitializers(CXXConstructorDecl *Constructor, bool AnyErrors,
                               ArrayRef<CXXCtorInitializer *> Initializers) {
  if (Constructor->isDependentContext()) {
    // Just store the initializers as written, they will be checked during
    // instantiation.
    if (!Initializers.empty()) {
      Constructor->setNumCtorInitializers(Initializers.size());
      CXXCtorInitializer **baseOrMemberInitializers =
        new (Context) CXXCtorInitializer*[Initializers.size()];
      memcpy(baseOrMemberInitializers, Initializers.data(),
             Initializers.size() * sizeof(CXXCtorInitializer*));
      Constructor->setCtorInitializers(baseOrMemberInitializers);
    }

    // Let template instantiation know whether we had errors.
    if (AnyErrors)
      Constructor->setInvalidDecl();

    return false;
  }

  BaseAndFieldInfo Info(*this, Constructor, AnyErrors);

  // We need to build the initializer AST according to order of construction
  // and not what user specified in the Initializers list.
  CXXRecordDecl *ClassDecl = Constructor->getParent()->getDefinition();
  if (!ClassDecl)
    return true;

  bool HadError = false;

  for (unsigned i = 0; i < Initializers.size(); i++) {
    CXXCtorInitializer *Member = Initializers[i];

    if (Member->isBaseInitializer())
      Info.AllBaseFields[Member->getBaseClass()->getAs<RecordType>()] = Member;
    else {
      Info.AllBaseFields[Member->getAnyMember()->getCanonicalDecl()] = Member;

      if (IndirectFieldDecl *F = Member->getIndirectMember()) {
        for (auto *C : F->chain()) {
          FieldDecl *FD = dyn_cast<FieldDecl>(C);
          if (FD && FD->getParent()->isUnion())
            Info.ActiveUnionMember.insert(std::make_pair(
                FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl()));
        }
      } else if (FieldDecl *FD = Member->getMember()) {
        if (FD->getParent()->isUnion())
          Info.ActiveUnionMember.insert(std::make_pair(
              FD->getParent()->getCanonicalDecl(), FD->getCanonicalDecl()));
      }
    }
  }

  // Keep track of the direct virtual bases.
  llvm::SmallPtrSet<CXXBaseSpecifier *, 16> DirectVBases;
  for (auto &I : ClassDecl->bases()) {
    if (I.isVirtual())
      DirectVBases.insert(&I);
  }

  // Push virtual bases before others.
  for (auto &VBase : ClassDecl->vbases()) {
    if (CXXCtorInitializer *Value
        = Info.AllBaseFields.lookup(VBase.getType()->getAs<RecordType>())) {
      // [class.base.init]p7, per DR257:
      //   A mem-initializer where the mem-initializer-id names a virtual base
      //   class is ignored during execution of a constructor of any class that
      //   is not the most derived class.
      if (ClassDecl->isAbstract()) {
        // FIXME: Provide a fixit to remove the base specifier. This requires
        // tracking the location of the associated comma for a base specifier.
        Diag(Value->getSourceLocation(), diag::warn_abstract_vbase_init_ignored)
          << VBase.getType() << ClassDecl;
        DiagnoseAbstractType(ClassDecl);
      }

      Info.AllToInit.push_back(Value);
    } else if (!AnyErrors && !ClassDecl->isAbstract()) {
      // [class.base.init]p8, per DR257:
      //   If a given [...] base class is not named by a mem-initializer-id
      //   [...] and the entity is not a virtual base class of an abstract
      //   class, then [...] the entity is default-initialized.
      bool IsInheritedVirtualBase = !DirectVBases.count(&VBase);
      CXXCtorInitializer *CXXBaseInit;
      if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
                                       &VBase, IsInheritedVirtualBase,
                                       CXXBaseInit)) {
        HadError = true;
        continue;
      }

      Info.AllToInit.push_back(CXXBaseInit);
    }
  }

  // Non-virtual bases.
  for (auto &Base : ClassDecl->bases()) {
    // Virtuals are in the virtual base list and already constructed.
    if (Base.isVirtual())
      continue;

    if (CXXCtorInitializer *Value
          = Info.AllBaseFields.lookup(Base.getType()->getAs<RecordType>())) {
      Info.AllToInit.push_back(Value);
    } else if (!AnyErrors) {
      CXXCtorInitializer *CXXBaseInit;
      if (BuildImplicitBaseInitializer(*this, Constructor, Info.IIK,
                                       &Base, /*IsInheritedVirtualBase=*/false,
                                       CXXBaseInit)) {
        HadError = true;
        continue;
      }

      Info.AllToInit.push_back(CXXBaseInit);
    }
  }

  // Fields.
  for (auto *Mem : ClassDecl->decls()) {
    if (auto *F = dyn_cast<FieldDecl>(Mem)) {
      // 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 (F->isUnnamedBitfield())
        continue;

      // If we're not generating the implicit copy/move constructor, then we'll
      // handle anonymous struct/union fields based on their individual
      // indirect fields.
      if (F->isAnonymousStructOrUnion() && !Info.isImplicitCopyOrMove())
        continue;

      if (CollectFieldInitializer(*this, Info, F))
        HadError = true;
      continue;
    }

    // Beyond this point, we only consider default initialization.
    if (Info.isImplicitCopyOrMove())
      continue;

    if (auto *F = dyn_cast<IndirectFieldDecl>(Mem)) {
      if (F->getType()->isIncompleteArrayType()) {
        assert(ClassDecl->hasFlexibleArrayMember() &&
               "Incomplete array type is not valid");
        continue;
      }

      // Initialize each field of an anonymous struct individually.
      if (CollectFieldInitializer(*this, Info, F->getAnonField(), F))
        HadError = true;

      continue;
    }
  }

  unsigned NumInitializers = Info.AllToInit.size();
  if (NumInitializers > 0) {
    Constructor->setNumCtorInitializers(NumInitializers);
    CXXCtorInitializer **baseOrMemberInitializers =
      new (Context) CXXCtorInitializer*[NumInitializers];
    memcpy(baseOrMemberInitializers, Info.AllToInit.data(),
           NumInitializers * sizeof(CXXCtorInitializer*));
    Constructor->setCtorInitializers(baseOrMemberInitializers);

    // Constructors implicitly reference the base and member
    // destructors.
    MarkBaseAndMemberDestructorsReferenced(Constructor->getLocation(),
                                           Constructor->getParent());
  }

  return HadError;
}

static void PopulateKeysForFields(FieldDecl *Field, SmallVectorImpl<const void*> &IdealInits) {
  if (const RecordType *RT = Field->getType()->getAs<RecordType>()) {
    const RecordDecl *RD = RT->getDecl();
    if (RD->isAnonymousStructOrUnion()) {
      for (auto *Field : RD->fields())
        PopulateKeysForFields(Field, IdealInits);
      return;
    }
  }
  IdealInits.push_back(Field->getCanonicalDecl());
}

static const void *GetKeyForBase(ASTContext &Context, QualType BaseType) {
  return Context.getCanonicalType(BaseType).getTypePtr();
}

static const void *GetKeyForMember(ASTContext &Context,
                                   CXXCtorInitializer *Member) {
  if (!Member->isAnyMemberInitializer())
    return GetKeyForBase(Context, QualType(Member->getBaseClass(), 0));

  return Member->getAnyMember()->getCanonicalDecl();
}

static void DiagnoseBaseOrMemInitializerOrder(
    Sema &SemaRef, const CXXConstructorDecl *Constructor,
    ArrayRef<CXXCtorInitializer *> Inits) {
  if (Constructor->getDeclContext()->isDependentContext())
    return;

  // Don't check initializers order unless the warning is enabled at the
  // location of at least one initializer.
  bool ShouldCheckOrder = false;
  for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
    CXXCtorInitializer *Init = Inits[InitIndex];
    if (!SemaRef.Diags.isIgnored(diag::warn_initializer_out_of_order,
                                 Init->getSourceLocation())) {
      ShouldCheckOrder = true;
      break;
    }
  }
  if (!ShouldCheckOrder)
    return;

  // Build the list of bases and members in the order that they'll
  // actually be initialized.  The explicit initializers should be in
  // this same order but may be missing things.
  SmallVector<const void*, 32> IdealInitKeys;

  const CXXRecordDecl *ClassDecl = Constructor->getParent();

  // 1. Virtual bases.
  for (const auto &VBase : ClassDecl->vbases())
    IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase.getType()));

  // 2. Non-virtual bases.
  for (const auto &Base : ClassDecl->bases()) {
    if (Base.isVirtual())
      continue;
    IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base.getType()));
  }

  // 3. Direct fields.
  for (auto *Field : ClassDecl->fields()) {
    if (Field->isUnnamedBitfield())
      continue;

    PopulateKeysForFields(Field, IdealInitKeys);
  }

  unsigned NumIdealInits = IdealInitKeys.size();
  unsigned IdealIndex = 0;

  CXXCtorInitializer *PrevInit = nullptr;
  for (unsigned InitIndex = 0; InitIndex != Inits.size(); ++InitIndex) {
    CXXCtorInitializer *Init = Inits[InitIndex];
    const void *InitKey = GetKeyForMember(SemaRef.Context, Init);

    // Scan forward to try to find this initializer in the idealized
    // initializers list.
    for (; IdealIndex != NumIdealInits; ++IdealIndex)
      if (InitKey == IdealInitKeys[IdealIndex])
        break;

    // If we didn't find this initializer, it must be because we
    // scanned past it on a previous iteration.  That can only
    // happen if we're out of order;  emit a warning.
    if (IdealIndex == NumIdealInits && PrevInit) {
      Sema::SemaDiagnosticBuilder D =
        SemaRef.Diag(PrevInit->getSourceLocation(),
                     diag::warn_initializer_out_of_order);

      if (PrevInit->isAnyMemberInitializer())
        D << 0 << PrevInit->getAnyMember()->getDeclName();
      else
        D << 1 << PrevInit->getTypeSourceInfo()->getType();

      if (Init->isAnyMemberInitializer())
        D << 0 << Init->getAnyMember()->getDeclName();
      else
        D << 1 << Init->getTypeSourceInfo()->getType();

      // Move back to the initializer's location in the ideal list.
      for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex)
        if (InitKey == IdealInitKeys[IdealIndex])
          break;

      assert(IdealIndex < NumIdealInits &&
             "initializer not found in initializer list");
    }

    PrevInit = Init;
  }
}

namespace {
bool CheckRedundantInit(Sema &S,
                        CXXCtorInitializer *Init,
                        CXXCtorInitializer *&PrevInit) {
  if (!PrevInit) {
    PrevInit = Init;
    return false;
  }

  if (FieldDecl *Field = Init->getAnyMember())
    S.Diag(Init->getSourceLocation(),
           diag::err_multiple_mem_initialization)
      << Field->getDeclName()
      << Init->getSourceRange();
  else {
    const Type *BaseClass = Init->getBaseClass();
    assert(BaseClass && "neither field nor base");
    S.Diag(Init->getSourceLocation(),
           diag::err_multiple_base_initialization)
      << QualType(BaseClass, 0)
      << Init->getSourceRange();
  }
  S.Diag(PrevInit->getSourceLocation(), diag::note_previous_initializer)
    << 0 << PrevInit->getSourceRange();

  return true;
}

typedef std::pair<NamedDecl *, CXXCtorInitializer *> UnionEntry;
typedef llvm::DenseMap<RecordDecl*, UnionEntry> RedundantUnionMap;

bool CheckRedundantUnionInit(Sema &S,
                             CXXCtorInitializer *Init,
                             RedundantUnionMap &Unions) {
  FieldDecl *Field = Init->getAnyMember();
  RecordDecl *Parent = Field->getParent();
  NamedDecl *Child = Field;

  while (Parent->isAnonymousStructOrUnion() || Parent->isUnion()) {
    if (Parent->isUnion()) {
      UnionEntry &En = Unions[Parent];
      if (En.first && En.first != Child) {
        S.Diag(Init->getSourceLocation(),
               diag::err_multiple_mem_union_initialization)
          << Field->getDeclName()
          << Init->getSourceRange();
        S.Diag(En.second->getSourceLocation(), diag::note_previous_initializer)
          << 0 << En.second->getSourceRange();
        return true;
      }
      if (!En.first) {
        En.first = Child;
        En.second = Init;
      }
      if (!Parent->isAnonymousStructOrUnion())
        return false;
    }

    Child = Parent;
    Parent = cast<RecordDecl>(Parent->getDeclContext());
  }

  return false;
}
}

/// ActOnMemInitializers - Handle the member initializers for a constructor.
void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
                                SourceLocation ColonLoc,
                                ArrayRef<CXXCtorInitializer*> MemInits,
                                bool AnyErrors) {
  if (!ConstructorDecl)
    return;

  AdjustDeclIfTemplate(ConstructorDecl);

  CXXConstructorDecl *Constructor
    = dyn_cast<CXXConstructorDecl>(ConstructorDecl);

  if (!Constructor) {
    Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
    return;
  }

  // Mapping for the duplicate initializers check.
  // For member initializers, this is keyed with a FieldDecl*.
  // For base initializers, this is keyed with a Type*.
  llvm::DenseMap<const void *, CXXCtorInitializer *> Members;

  // Mapping for the inconsistent anonymous-union initializers check.
  RedundantUnionMap MemberUnions;

  bool HadError = false;
  for (unsigned i = 0; i < MemInits.size(); i++) {
    CXXCtorInitializer *Init = MemInits[i];

    // Set the source order index.
    Init->setSourceOrder(i);

    if (Init->isAnyMemberInitializer()) {
      const void *Key = GetKeyForMember(Context, Init);
      if (CheckRedundantInit(*this, Init, Members[Key]) ||
          CheckRedundantUnionInit(*this, Init, MemberUnions))
        HadError = true;
    } else if (Init->isBaseInitializer()) {
      const void *Key = GetKeyForMember(Context, Init);
      if (CheckRedundantInit(*this, Init, Members[Key]))
        HadError = true;
    } else {
      assert(Init->isDelegatingInitializer());
      // This must be the only initializer
      if (MemInits.size() != 1) {
        Diag(Init->getSourceLocation(),
             diag::err_delegating_initializer_alone)
          << Init->getSourceRange() << MemInits[i ? 0 : 1]->getSourceRange();
        // We will treat this as being the only initializer.
      }
      SetDelegatingInitializer(Constructor, MemInits[i]);
      // Return immediately as the initializer is set.
      return;
    }
  }

  if (HadError)
    return;

  DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits);

  SetCtorInitializers(Constructor, AnyErrors, MemInits);

  DiagnoseUninitializedFields(*this, Constructor);
}

void
Sema::MarkBaseAndMemberDestructorsReferenced(SourceLocation Location,
                                             CXXRecordDecl *ClassDecl) {
  // Ignore dependent contexts. Also ignore unions, since their members never
  // have destructors implicitly called.
  if (ClassDecl->isDependentContext() || ClassDecl->isUnion())
    return;

  // FIXME: all the access-control diagnostics are positioned on the
  // field/base declaration.  That's probably good; that said, the
  // user might reasonably want to know why the destructor is being
  // emitted, and we currently don't say.

  // Non-static data members.
  for (auto *Field : ClassDecl->fields()) {
    if (Field->isInvalidDecl())
      continue;

    // Don't destroy incomplete or zero-length arrays.
    if (isIncompleteOrZeroLengthArrayType(Context, Field->getType()))
      continue;

    QualType FieldType = Context.getBaseElementType(Field->getType());

    const RecordType* RT = FieldType->getAs<RecordType>();
    if (!RT)
      continue;

    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
    if (FieldClassDecl->isInvalidDecl())
      continue;
    if (FieldClassDecl->hasIrrelevantDestructor())
      continue;
    // The destructor for an implicit anonymous union member is never invoked.
    if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
      continue;

    CXXDestructorDecl *Dtor = LookupDestructor(FieldClassDecl);
    assert(Dtor && "No dtor found for FieldClassDecl!");
    CheckDestructorAccess(Field->getLocation(), Dtor,
                          PDiag(diag::err_access_dtor_field)
                            << Field->getDeclName()
                            << FieldType);

    MarkFunctionReferenced(Location, Dtor);
    DiagnoseUseOfDecl(Dtor, Location);
  }

  // We only potentially invoke the destructors of potentially constructed
  // subobjects.
  bool VisitVirtualBases = !ClassDecl->isAbstract();

  llvm::SmallPtrSet<const RecordType *, 8> DirectVirtualBases;

  // Bases.
  for (const auto &Base : ClassDecl->bases()) {
    // Bases are always records in a well-formed non-dependent class.
    const RecordType *RT = Base.getType()->getAs<RecordType>();

    // Remember direct virtual bases.
    if (Base.isVirtual()) {
      if (!VisitVirtualBases)
        continue;
      DirectVirtualBases.insert(RT);
    }

    CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
    // If our base class is invalid, we probably can't get its dtor anyway.
    if (BaseClassDecl->isInvalidDecl())
      continue;
    if (BaseClassDecl->hasIrrelevantDestructor())
      continue;

    CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
    assert(Dtor && "No dtor found for BaseClassDecl!");

    // FIXME: caret should be on the start of the class name
    CheckDestructorAccess(Base.getBeginLoc(), Dtor,
                          PDiag(diag::err_access_dtor_base)
                              << Base.getType() << Base.getSourceRange(),
                          Context.getTypeDeclType(ClassDecl));

    MarkFunctionReferenced(Location, Dtor);
    DiagnoseUseOfDecl(Dtor, Location);
  }

  if (!VisitVirtualBases)
    return;

  // Virtual bases.
  for (const auto &VBase : ClassDecl->vbases()) {
    // Bases are always records in a well-formed non-dependent class.
    const RecordType *RT = VBase.getType()->castAs<RecordType>();

    // Ignore direct virtual bases.
    if (DirectVirtualBases.count(RT))
      continue;

    CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl());
    // If our base class is invalid, we probably can't get its dtor anyway.
    if (BaseClassDecl->isInvalidDecl())
      continue;
    if (BaseClassDecl->hasIrrelevantDestructor())
      continue;

    CXXDestructorDecl *Dtor = LookupDestructor(BaseClassDecl);
    assert(Dtor && "No dtor found for BaseClassDecl!");
    if (CheckDestructorAccess(
            ClassDecl->getLocation(), Dtor,
            PDiag(diag::err_access_dtor_vbase)
                << Context.getTypeDeclType(ClassDecl) << VBase.getType(),
            Context.getTypeDeclType(ClassDecl)) ==
        AR_accessible) {
      CheckDerivedToBaseConversion(
          Context.getTypeDeclType(ClassDecl), VBase.getType(),
          diag::err_access_dtor_vbase, 0, ClassDecl->getLocation(),
          SourceRange(), DeclarationName(), nullptr);
    }

    MarkFunctionReferenced(Location, Dtor);
    DiagnoseUseOfDecl(Dtor, Location);
  }
}

void Sema::ActOnDefaultCtorInitializers(Decl *CDtorDecl) {
  if (!CDtorDecl)
    return;

  if (CXXConstructorDecl *Constructor
      = dyn_cast<CXXConstructorDecl>(CDtorDecl)) {
    SetCtorInitializers(Constructor, /*AnyErrors=*/false);
    DiagnoseUninitializedFields(*this, Constructor);
  }
}

bool Sema::isAbstractType(SourceLocation Loc, QualType T) {
  if (!getLangOpts().CPlusPlus)
    return false;

  const auto *RD = Context.getBaseElementType(T)->getAsCXXRecordDecl();
  if (!RD)
    return false;

  // FIXME: Per [temp.inst]p1, we are supposed to trigger instantiation of a
  // class template specialization here, but doing so breaks a lot of code.

  // We can't answer whether something is abstract until it has a
  // definition. If it's currently being defined, we'll walk back
  // over all the declarations when we have a full definition.
  const CXXRecordDecl *Def = RD->getDefinition();
  if (!Def || Def->isBeingDefined())
    return false;

  return RD->isAbstract();
}

bool Sema::RequireNonAbstractType(SourceLocation Loc, QualType T,
                                  TypeDiagnoser &Diagnoser) {
  if (!isAbstractType(Loc, T))
    return false;

  T = Context.getBaseElementType(T);
  Diagnoser.diagnose(*this, Loc, T);
  DiagnoseAbstractType(T->getAsCXXRecordDecl());
  return true;
}

void Sema::DiagnoseAbstractType(const CXXRecordDecl *RD) {
  // Check if we've already emitted the list of pure virtual functions
  // for this class.
  if (PureVirtualClassDiagSet && PureVirtualClassDiagSet->count(RD))
    return;

  // If the diagnostic is suppressed, don't emit the notes. We're only
  // going to emit them once, so try to attach them to a diagnostic we're
  // actually going to show.
  if (Diags.isLastDiagnosticIgnored())
    return;

  CXXFinalOverriderMap FinalOverriders;
  RD->getFinalOverriders(FinalOverriders);

  // Keep a set of seen pure methods so we won't diagnose the same method
  // more than once.
  llvm::SmallPtrSet<const CXXMethodDecl *, 8> SeenPureMethods;

  for (CXXFinalOverriderMap::iterator M = FinalOverriders.begin(),
                                   MEnd = FinalOverriders.end();
       M != MEnd;
       ++M) {
    for (OverridingMethods::iterator SO = M->second.begin(),
                                  SOEnd = M->second.end();
         SO != SOEnd; ++SO) {
      // 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.size() != 1)
        continue;

      if (!SO->second.front().Method->isPure())
        continue;

      if (!SeenPureMethods.insert(SO->second.front().Method).second)
        continue;

      Diag(SO->second.front().Method->getLocation(),
           diag::note_pure_virtual_function)
        << SO->second.front().Method->getDeclName() << RD->getDeclName();
    }
  }

  if (!PureVirtualClassDiagSet)
    PureVirtualClassDiagSet.reset(new RecordDeclSetTy);
  PureVirtualClassDiagSet->insert(RD);
}

namespace {
struct AbstractUsageInfo {
  Sema &S;
  CXXRecordDecl *Record;
  CanQualType AbstractType;
  bool Invalid;

  AbstractUsageInfo(Sema &S, CXXRecordDecl *Record)
    : S(S), Record(Record),
      AbstractType(S.Context.getCanonicalType(
                   S.Context.getTypeDeclType(Record))),
      Invalid(false) {}

  void DiagnoseAbstractType() {
    if (Invalid) return;
    S.DiagnoseAbstractType(Record);
    Invalid = true;
  }

  void CheckType(const NamedDecl *D, TypeLoc TL, Sema::AbstractDiagSelID Sel);
};

struct CheckAbstractUsage {
  AbstractUsageInfo &Info;
  const NamedDecl *Ctx;

  CheckAbstractUsage(AbstractUsageInfo &Info, const NamedDecl *Ctx)
    : Info(Info), Ctx(Ctx) {}

  void Visit(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
    switch (TL.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
    case TypeLoc::CLASS: Check(TL.castAs<CLASS##TypeLoc>(), Sel); break;
#include "clang/AST/TypeLocNodes.def"
    }
  }

  void Check(FunctionProtoTypeLoc TL, Sema::AbstractDiagSelID Sel) {
    Visit(TL.getReturnLoc(), Sema::AbstractReturnType);
    for (unsigned I = 0, E = TL.getNumParams(); I != E; ++I) {
      if (!TL.getParam(I))
        continue;

      TypeSourceInfo *TSI = TL.getParam(I)->getTypeSourceInfo();
      if (TSI) Visit(TSI->getTypeLoc(), Sema::AbstractParamType);
    }
  }

  void Check(ArrayTypeLoc TL, Sema::AbstractDiagSelID Sel) {
    Visit(TL.getElementLoc(), Sema::AbstractArrayType);
  }

  void Check(TemplateSpecializationTypeLoc TL, Sema::AbstractDiagSelID Sel) {
    // Visit the type parameters from a permissive context.
    for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
      TemplateArgumentLoc TAL = TL.getArgLoc(I);
      if (TAL.getArgument().getKind() == TemplateArgument::Type)
        if (TypeSourceInfo *TSI = TAL.getTypeSourceInfo())
          Visit(TSI->getTypeLoc(), Sema::AbstractNone);
      // TODO: other template argument types?
    }
  }

  // Visit pointee types from a permissive context.
#define CheckPolymorphic(Type) \
  void Check(Type TL, Sema::AbstractDiagSelID Sel) { \
    Visit(TL.getNextTypeLoc(), Sema::AbstractNone); \
  }
  CheckPolymorphic(PointerTypeLoc)
  CheckPolymorphic(ReferenceTypeLoc)
  CheckPolymorphic(MemberPointerTypeLoc)
  CheckPolymorphic(BlockPointerTypeLoc)
  CheckPolymorphic(AtomicTypeLoc)

  /// Handle all the types we haven't given a more specific
  /// implementation for above.
  void Check(TypeLoc TL, Sema::AbstractDiagSelID Sel) {
    // Every other kind of type that we haven't called out already
    // that has an inner type is either (1) sugar or (2) contains that
    // inner type in some way as a subobject.
    if (TypeLoc Next = TL.getNextTypeLoc())
      return Visit(Next, Sel);

    // If there's no inner type and we're in a permissive context,
    // don't diagnose.
    if (Sel == Sema::AbstractNone) return;

    // Check whether the type matches the abstract type.
    QualType T = TL.getType();
    if (T->isArrayType()) {
      Sel = Sema::AbstractArrayType;
      T = Info.S.Context.getBaseElementType(T);
    }
    CanQualType CT = T->getCanonicalTypeUnqualified().getUnqualifiedType();
    if (CT != Info.AbstractType) return;

    // It matched; do some magic.
    if (Sel == Sema::AbstractArrayType) {
      Info.S.Diag(Ctx->getLocation(), diag::err_array_of_abstract_type)
        << T << TL.getSourceRange();
    } else {
      Info.S.Diag(Ctx->getLocation(), diag::err_abstract_type_in_decl)
        << Sel << T << TL.getSourceRange();
    }
    Info.DiagnoseAbstractType();
  }
};

void AbstractUsageInfo::CheckType(const NamedDecl *D, TypeLoc TL,
                                  Sema::AbstractDiagSelID Sel) {
  CheckAbstractUsage(*this, D).Visit(TL, Sel);
}

}

/// Check for invalid uses of an abstract type in a method declaration.
static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
                                    CXXMethodDecl *MD) {
  // No need to do the check on definitions, which require that
  // the return/param types be complete.
  if (MD->doesThisDeclarationHaveABody())
    return;

  // For safety's sake, just ignore it if we don't have type source
  // information.  This should never happen for non-implicit methods,
  // but...
  if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
    Info.CheckType(MD, TSI->getTypeLoc(), Sema::AbstractNone);
}

/// Check for invalid uses of an abstract type within a class definition.
static void CheckAbstractClassUsage(AbstractUsageInfo &Info,
                                    CXXRecordDecl *RD) {
  for (auto *D : RD->decls()) {
    if (D->isImplicit()) continue;

    // Methods and method templates.
    if (isa<CXXMethodDecl>(D)) {
      CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(D));
    } else if (isa<FunctionTemplateDecl>(D)) {
      FunctionDecl *FD = cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
      CheckAbstractClassUsage(Info, cast<CXXMethodDecl>(FD));

    // Fields and static variables.
    } else if (isa<FieldDecl>(D)) {
      FieldDecl *FD = cast<FieldDecl>(D);
      if (TypeSourceInfo *TSI = FD->getTypeSourceInfo())
        Info.CheckType(FD, TSI->getTypeLoc(), Sema::AbstractFieldType);
    } else if (isa<VarDecl>(D)) {
      VarDecl *VD = cast<VarDecl>(D);
      if (TypeSourceInfo *TSI = VD->getTypeSourceInfo())
        Info.CheckType(VD, TSI->getTypeLoc(), Sema::AbstractVariableType);

    // Nested classes and class templates.
    } else if (isa<CXXRecordDecl>(D)) {
      CheckAbstractClassUsage(Info, cast<CXXRecordDecl>(D));
    } else if (isa<ClassTemplateDecl>(D)) {
      CheckAbstractClassUsage(Info,
                             cast<ClassTemplateDecl>(D)->getTemplatedDecl());
    }
  }
}

static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
  Attr *ClassAttr = getDLLAttr(Class);
  if (!ClassAttr)
    return;

  assert(ClassAttr->getKind() == attr::DLLExport);

  TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();

  if (TSK == TSK_ExplicitInstantiationDeclaration)
    // Don't go any further if this is just an explicit instantiation
    // declaration.
    return;

  if (S.Context.getTargetInfo().getTriple().isWindowsGNUEnvironment())
    S.MarkVTableUsed(Class->getLocation(), Class, true);

  for (Decl *Member : Class->decls()) {
    // Defined static variables that are members of an exported base
    // class must be marked export too.
    auto *VD = dyn_cast<VarDecl>(Member);
    if (VD && Member->getAttr<DLLExportAttr>() &&
        VD->getStorageClass() == SC_Static &&
        TSK == TSK_ImplicitInstantiation)
      S.MarkVariableReferenced(VD->getLocation(), VD);

    auto *MD = dyn_cast<CXXMethodDecl>(Member);
    if (!MD)
      continue;

    if (Member->getAttr<DLLExportAttr>()) {
      if (MD->isUserProvided()) {
        // Instantiate non-default class member functions ...

        // .. except for certain kinds of template specializations.
        if (TSK == TSK_ImplicitInstantiation && !ClassAttr->isInherited())
          continue;

        S.MarkFunctionReferenced(Class->getLocation(), MD);

        // The function will be passed to the consumer when its definition is
        // encountered.
      } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() ||
                 MD->isCopyAssignmentOperator() ||
                 MD->isMoveAssignmentOperator()) {
        // Synthesize and instantiate non-trivial implicit methods, explicitly
        // defaulted methods, and the copy and move assignment operators. The
        // latter are exported even if they are trivial, because the address of
        // an operator can be taken and should compare equal across libraries.
        DiagnosticErrorTrap Trap(S.Diags);
        S.MarkFunctionReferenced(Class->getLocation(), MD);
        if (Trap.hasErrorOccurred()) {
          S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
              << Class << !S.getLangOpts().CPlusPlus11;
          break;
        }

        // There is no later point when we will see the definition of this
        // function, so pass it to the consumer now.
        S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD));
      }
    }
  }
}

static void checkForMultipleExportedDefaultConstructors(Sema &S,
                                                        CXXRecordDecl *Class) {
  // Only the MS ABI has default constructor closures, so we don't need to do
  // this semantic checking anywhere else.
  if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft())
    return;

  CXXConstructorDecl *LastExportedDefaultCtor = nullptr;
  for (Decl *Member : Class->decls()) {
    // Look for exported default constructors.
    auto *CD = dyn_cast<CXXConstructorDecl>(Member);
    if (!CD || !CD->isDefaultConstructor())
      continue;
    auto *Attr = CD->getAttr<DLLExportAttr>();
    if (!Attr)
      continue;

    // If the class is non-dependent, mark the default arguments as ODR-used so
    // that we can properly codegen the constructor closure.
    if (!Class->isDependentContext()) {
      for (ParmVarDecl *PD : CD->parameters()) {
        (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), CD, PD);
        S.DiscardCleanupsInEvaluationContext();
      }
    }

    if (LastExportedDefaultCtor) {
      S.Diag(LastExportedDefaultCtor->getLocation(),
             diag::err_attribute_dll_ambiguous_default_ctor)
          << Class;
      S.Diag(CD->getLocation(), diag::note_entity_declared_at)
          << CD->getDeclName();
      return;
    }
    LastExportedDefaultCtor = CD;
  }
}

void Sema::checkClassLevelCodeSegAttribute(CXXRecordDecl *Class) {
  // Mark any compiler-generated routines with the implicit code_seg attribute.
  for (auto *Method : Class->methods()) {
    if (Method->isUserProvided())
      continue;
    if (Attr *A = getImplicitCodeSegOrSectionAttrForFunction(Method, /*IsDefinition=*/true))
      Method->addAttr(A);
  }
}

/// Check class-level dllimport/dllexport attribute.
void Sema::checkClassLevelDLLAttribute(CXXRecordDecl *Class) {
  Attr *ClassAttr = getDLLAttr(Class);

  // MSVC inherits DLL attributes to partial class template specializations.
  if (Context.getTargetInfo().getCXXABI().isMicrosoft() && !ClassAttr) {
    if (auto *Spec = dyn_cast<ClassTemplatePartialSpecializationDecl>(Class)) {
      if (Attr *TemplateAttr =
              getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) {
        auto *A = cast<InheritableAttr>(TemplateAttr->clone(getASTContext()));
        A->setInherited(true);
        ClassAttr = A;
      }
    }
  }

  if (!ClassAttr)
    return;

  if (!Class->isExternallyVisible()) {
    Diag(Class->getLocation(), diag::err_attribute_dll_not_extern)
        << Class << ClassAttr;
    return;
  }

  if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
      !ClassAttr->isInherited()) {
    // Diagnose dll attributes on members of class with dll attribute.
    for (Decl *Member : Class->decls()) {
      if (!isa<VarDecl>(Member) && !isa<CXXMethodDecl>(Member))
        continue;
      InheritableAttr *MemberAttr = getDLLAttr(Member);
      if (!MemberAttr || MemberAttr->isInherited() || Member->isInvalidDecl())
        continue;

      Diag(MemberAttr->getLocation(),
             diag::err_attribute_dll_member_of_dll_class)
          << MemberAttr << ClassAttr;
      Diag(ClassAttr->getLocation(), diag::note_previous_attribute);
      Member->setInvalidDecl();
    }
  }

  if (Class->getDescribedClassTemplate())
    // Don't inherit dll attribute until the template is instantiated.
    return;

  // The class is either imported or exported.
  const bool ClassExported = ClassAttr->getKind() == attr::DLLExport;

  // Check if this was a dllimport attribute propagated from a derived class to
  // a base class template specialization. We don't apply these attributes to
  // static data members.
  const bool PropagatedImport =
      !ClassExported &&
      cast<DLLImportAttr>(ClassAttr)->wasPropagatedToBaseTemplate();

  TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();

  // Ignore explicit dllexport on explicit class template instantiation
  // declarations, except in MinGW mode.
  if (ClassExported && !ClassAttr->isInherited() &&
      TSK == TSK_ExplicitInstantiationDeclaration &&
      !Context.getTargetInfo().getTriple().isWindowsGNUEnvironment()) {
    Class->dropAttr<DLLExportAttr>();
    return;
  }

  // Force declaration of implicit members so they can inherit the attribute.
  ForceDeclarationOfImplicitMembers(Class);

  // FIXME: MSVC's docs say all bases must be exportable, but this doesn't
  // seem to be true in practice?

  for (Decl *Member : Class->decls()) {
    VarDecl *VD = dyn_cast<VarDecl>(Member);
    CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);

    // Only methods and static fields inherit the attributes.
    if (!VD && !MD)
      continue;

    if (MD) {
      // Don't process deleted methods.
      if (MD->isDeleted())
        continue;

      if (MD->isInlined()) {
        // MinGW does not import or export inline methods. But do it for
        // template instantiations.
        if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
            !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment() &&
            TSK != TSK_ExplicitInstantiationDeclaration &&
            TSK != TSK_ExplicitInstantiationDefinition)
          continue;

        // MSVC versions before 2015 don't export the move assignment operators
        // and move constructor, so don't attempt to import/export them if
        // we have a definition.
        auto *Ctor = dyn_cast<CXXConstructorDecl>(MD);
        if ((MD->isMoveAssignmentOperator() ||
             (Ctor && Ctor->isMoveConstructor())) &&
            !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015))
          continue;

        // MSVC2015 doesn't export trivial defaulted x-tor but copy assign
        // operator is exported anyway.
        if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
            (Ctor || isa<CXXDestructorDecl>(MD)) && MD->isTrivial())
          continue;
      }
    }

    // Don't apply dllimport attributes to static data members of class template
    // instantiations when the attribute is propagated from a derived class.
    if (VD && PropagatedImport)
      continue;

    if (!cast<NamedDecl>(Member)->isExternallyVisible())
      continue;

    if (!getDLLAttr(Member)) {
      InheritableAttr *NewAttr = nullptr;

      // Do not export/import inline function when -fno-dllexport-inlines is
      // passed. But add attribute for later local static var check.
      if (!getLangOpts().DllExportInlines && MD && MD->isInlined() &&
          TSK != TSK_ExplicitInstantiationDeclaration &&
          TSK != TSK_ExplicitInstantiationDefinition) {
        if (ClassExported) {
          NewAttr = ::new (getASTContext())
            DLLExportStaticLocalAttr(ClassAttr->getRange(),
                                     getASTContext(),
                                     ClassAttr->getSpellingListIndex());
        } else {
          NewAttr = ::new (getASTContext())
            DLLImportStaticLocalAttr(ClassAttr->getRange(),
                                     getASTContext(),
                                     ClassAttr->getSpellingListIndex());
        }
      } else {
        NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
      }

      NewAttr->setInherited(true);
      Member->addAttr(NewAttr);

      if (MD) {
        // Propagate DLLAttr to friend re-declarations of MD that have already
        // been constructed.
        for (FunctionDecl *FD = MD->getMostRecentDecl(); FD;
             FD = FD->getPreviousDecl()) {
          if (FD->getFriendObjectKind() == Decl::FOK_None)
            continue;
          assert(!getDLLAttr(FD) &&
                 "friend re-decl should not already have a DLLAttr");
          NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
          NewAttr->setInherited(true);
          FD->addAttr(NewAttr);
        }
      }
    }
  }

  if (ClassExported)
    DelayedDllExportClasses.push_back(Class);
}

/// Perform propagation of DLL attributes from a derived class to a
/// templated base class for MS compatibility.
void Sema::propagateDLLAttrToBaseClassTemplate(
    CXXRecordDecl *Class, Attr *ClassAttr,
    ClassTemplateSpecializationDecl *BaseTemplateSpec, SourceLocation BaseLoc) {
  if (getDLLAttr(
          BaseTemplateSpec->getSpecializedTemplate()->getTemplatedDecl())) {
    // If the base class template has a DLL attribute, don't try to change it.
    return;
  }

  auto TSK = BaseTemplateSpec->getSpecializationKind();
  if (!getDLLAttr(BaseTemplateSpec) &&
      (TSK == TSK_Undeclared || TSK == TSK_ExplicitInstantiationDeclaration ||
       TSK == TSK_ImplicitInstantiation)) {
    // The template hasn't been instantiated yet (or it has, but only as an
    // explicit instantiation declaration or implicit instantiation, which means
    // we haven't codegenned any members yet), so propagate the attribute.
    auto *NewAttr = cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
    NewAttr->setInherited(true);
    BaseTemplateSpec->addAttr(NewAttr);

    // If this was an import, mark that we propagated it from a derived class to
    // a base class template specialization.
    if (auto *ImportAttr = dyn_cast<DLLImportAttr>(NewAttr))
      ImportAttr->setPropagatedToBaseTemplate();

    // If the template is already instantiated, checkDLLAttributeRedeclaration()
    // needs to be run again to work see the new attribute. Otherwise this will
    // get run whenever the template is instantiated.
    if (TSK != TSK_Undeclared)
      checkClassLevelDLLAttribute(BaseTemplateSpec);

    return;
  }

  if (getDLLAttr(BaseTemplateSpec)) {
    // The template has already been specialized or instantiated with an
    // attribute, explicitly or through propagation. We should not try to change
    // it.
    return;
  }

  // The template was previously instantiated or explicitly specialized without
  // a dll attribute, It's too late for us to add an attribute, so warn that
  // this is unsupported.
  Diag(BaseLoc, diag::warn_attribute_dll_instantiated_base_class)
      << BaseTemplateSpec->isExplicitSpecialization();
  Diag(ClassAttr->getLocation(), diag::note_attribute);
  if (BaseTemplateSpec->isExplicitSpecialization()) {
    Diag(BaseTemplateSpec->getLocation(),
           diag::note_template_class_explicit_specialization_was_here)
        << BaseTemplateSpec;
  } else {
    Diag(BaseTemplateSpec->getPointOfInstantiation(),
           diag::note_template_class_instantiation_was_here)
        << BaseTemplateSpec;
  }
}

static void DefineImplicitSpecialMember(Sema &S, CXXMethodDecl *MD,
                                        SourceLocation DefaultLoc) {
  switch (S.getSpecialMember(MD)) {
  case Sema::CXXDefaultConstructor:
    S.DefineImplicitDefaultConstructor(DefaultLoc,
                                       cast<CXXConstructorDecl>(MD));
    break;
  case Sema::CXXCopyConstructor:
    S.DefineImplicitCopyConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
    break;
  case Sema::CXXCopyAssignment:
    S.DefineImplicitCopyAssignment(DefaultLoc, MD);
    break;
  case Sema::CXXDestructor:
    S.DefineImplicitDestructor(DefaultLoc, cast<CXXDestructorDecl>(MD));
    break;
  case Sema::CXXMoveConstructor:
    S.DefineImplicitMoveConstructor(DefaultLoc, cast<CXXConstructorDecl>(MD));
    break;
  case Sema::CXXMoveAssignment:
    S.DefineImplicitMoveAssignment(DefaultLoc, MD);
    break;
  case Sema::CXXInvalid:
    llvm_unreachable("Invalid special member.");
  }
}

/// Determine whether a type is permitted to be passed or returned in
/// registers, per C++ [class.temporary]p3.
static bool canPassInRegisters(Sema &S, CXXRecordDecl *D,
                               TargetInfo::CallingConvKind CCK) {
  if (D->isDependentType() || D->isInvalidDecl())
    return false;

  // Clang <= 4 used the pre-C++11 rule, which ignores move operations.
  // The PS4 platform ABI follows the behavior of Clang 3.2.
  if (CCK == TargetInfo::CCK_ClangABI4OrPS4)
    return !D->hasNonTrivialDestructorForCall() &&
           !D->hasNonTrivialCopyConstructorForCall();

  if (CCK == TargetInfo::CCK_MicrosoftWin64) {
    bool CopyCtorIsTrivial = false, CopyCtorIsTrivialForCall = false;
    bool DtorIsTrivialForCall = false;

    // If a class has at least one non-deleted, trivial copy constructor, it
    // is passed according to the C ABI. Otherwise, it is passed indirectly.
    //
    // Note: This permits classes with non-trivial copy or move ctors to be
    // passed in registers, so long as they *also* have a trivial copy ctor,
    // which is non-conforming.
    if (D->needsImplicitCopyConstructor()) {
      if (!D->defaultedCopyConstructorIsDeleted()) {
        if (D->hasTrivialCopyConstructor())
          CopyCtorIsTrivial = true;
        if (D->hasTrivialCopyConstructorForCall())
          CopyCtorIsTrivialForCall = true;
      }
    } else {
      for (const CXXConstructorDecl *CD : D->ctors()) {
        if (CD->isCopyConstructor() && !CD->isDeleted()) {
          if (CD->isTrivial())
            CopyCtorIsTrivial = true;
          if (CD->isTrivialForCall())
            CopyCtorIsTrivialForCall = true;
        }
      }
    }

    if (D->needsImplicitDestructor()) {
      if (!D->defaultedDestructorIsDeleted() &&
          D->hasTrivialDestructorForCall())
        DtorIsTrivialForCall = true;
    } else if (const auto *DD = D->getDestructor()) {
      if (!DD->isDeleted() && DD->isTrivialForCall())
        DtorIsTrivialForCall = true;
    }

    // If the copy ctor and dtor are both trivial-for-calls, pass direct.
    if (CopyCtorIsTrivialForCall && DtorIsTrivialForCall)
      return true;

    // If a class has a destructor, we'd really like to pass it indirectly
    // because it allows us to elide copies.  Unfortunately, MSVC makes that
    // impossible for small types, which it will pass in a single register or
    // stack slot. Most objects with dtors are large-ish, so handle that early.
    // We can't call out all large objects as being indirect because there are
    // multiple x64 calling conventions and the C++ ABI code shouldn't dictate
    // how we pass large POD types.

    // Note: This permits small classes with nontrivial destructors to be
    // passed in registers, which is non-conforming.
    bool isAArch64 = S.Context.getTargetInfo().getTriple().isAArch64();
    uint64_t TypeSize = isAArch64 ? 128 : 64;

    if (CopyCtorIsTrivial &&
        S.getASTContext().getTypeSize(D->getTypeForDecl()) <= TypeSize)
      return true;
    return false;
  }

  // Per C++ [class.temporary]p3, the relevant condition is:
  //   each copy constructor, move constructor, and destructor of X is
  //   either trivial or deleted, and X has at least one non-deleted copy
  //   or move constructor
  bool HasNonDeletedCopyOrMove = false;

  if (D->needsImplicitCopyConstructor() &&
      !D->defaultedCopyConstructorIsDeleted()) {
    if (!D->hasTrivialCopyConstructorForCall())
      return false;
    HasNonDeletedCopyOrMove = true;
  }

  if (S.getLangOpts().CPlusPlus11 && D->needsImplicitMoveConstructor() &&
      !D->defaultedMoveConstructorIsDeleted()) {
    if (!D->hasTrivialMoveConstructorForCall())
      return false;
    HasNonDeletedCopyOrMove = true;
  }

  if (D->needsImplicitDestructor() && !D->defaultedDestructorIsDeleted() &&
      !D->hasTrivialDestructorForCall())
    return false;

  for (const CXXMethodDecl *MD : D->methods()) {
    if (MD->isDeleted())
      continue;

    auto *CD = dyn_cast<CXXConstructorDecl>(MD);
    if (CD && CD->isCopyOrMoveConstructor())
      HasNonDeletedCopyOrMove = true;
    else if (!isa<CXXDestructorDecl>(MD))
      continue;

    if (!MD->isTrivialForCall())
      return false;
  }

  return HasNonDeletedCopyOrMove;
}

/// Perform semantic checks on a class definition that has been
/// completing, introducing implicitly-declared members, checking for
/// abstract types, etc.
void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
  if (!Record)
    return;

  if (Record->isAbstract() && !Record->isInvalidDecl()) {
    AbstractUsageInfo Info(*this, Record);
    CheckAbstractClassUsage(Info, Record);
  }

  // If this is not an aggregate type and has no user-declared constructor,
  // complain about any non-static data members of reference or const scalar
  // type, since they will never get initializers.
  if (!Record->isInvalidDecl() && !Record->isDependentType() &&
      !Record->isAggregate() && !Record->hasUserDeclaredConstructor() &&
      !Record->isLambda()) {
    bool Complained = false;
    for (const auto *F : Record->fields()) {
      if (F->hasInClassInitializer() || F->isUnnamedBitfield())
        continue;

      if (F->getType()->isReferenceType() ||
          (F->getType().isConstQualified() && F->getType()->isScalarType())) {
        if (!Complained) {
          Diag(Record->getLocation(), diag::warn_no_constructor_for_refconst)
            << Record->getTagKind() << Record;
          Complained = true;
        }

        Diag(F->getLocation(), diag::note_refconst_member_not_initialized)
          << F->getType()->isReferenceType()
          << F->getDeclName();
      }
    }
  }

  if (Record->getIdentifier()) {
    // C++ [class.mem]p13:
    //   If T is the name of a class, then each of the following shall have a
    //   name different from T:
    //     - every member of every anonymous union that is a member of class T.
    //
    // C++ [class.mem]p14:
    //   In addition, if class T has a user-declared constructor (12.1), every
    //   non-static data member of class T shall have a name different from T.
    DeclContext::lookup_result R = Record->lookup(Record->getDeclName());
    for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E;
         ++I) {
      NamedDecl *D = (*I)->getUnderlyingDecl();
      if (((isa<FieldDecl>(D) || isa<UnresolvedUsingValueDecl>(D)) &&
           Record->hasUserDeclaredConstructor()) ||
          isa<IndirectFieldDecl>(D)) {
        Diag((*I)->getLocation(), diag::err_member_name_of_class)
          << D->getDeclName();
        break;
      }
    }
  }

  // Warn if the class has virtual methods but non-virtual public destructor.
  if (Record->isPolymorphic() && !Record->isDependentType()) {
    CXXDestructorDecl *dtor = Record->getDestructor();
    if ((!dtor || (!dtor->isVirtual() && dtor->getAccess() == AS_public)) &&
        !Record->hasAttr<FinalAttr>())
      Diag(dtor ? dtor->getLocation() : Record->getLocation(),
           diag::warn_non_virtual_dtor) << Context.getRecordType(Record);
  }

  if (Record->isAbstract()) {
    if (FinalAttr *FA = Record->getAttr<FinalAttr>()) {
      Diag(Record->getLocation(), diag::warn_abstract_final_class)
        << FA->isSpelledAsSealed();
      DiagnoseAbstractType(Record);
    }
  }

  // See if trivial_abi has to be dropped.
  if (Record->hasAttr<TrivialABIAttr>())
    checkIllFormedTrivialABIStruct(*Record);

  // Set HasTrivialSpecialMemberForCall if the record has attribute
  // "trivial_abi".
  bool HasTrivialABI = Record->hasAttr<TrivialABIAttr>();

  if (HasTrivialABI)
    Record->setHasTrivialSpecialMemberForCall();

  bool HasMethodWithOverrideControl = false,
       HasOverridingMethodWithoutOverrideControl = false;
  if (!Record->isDependentType()) {
    for (auto *M : Record->methods()) {
      // See if a method overloads virtual methods in a base
      // class without overriding any.
      if (!M->isStatic())
        DiagnoseHiddenVirtualMethods(M);
      if (M->hasAttr<OverrideAttr>())
        HasMethodWithOverrideControl = true;
      else if (M->size_overridden_methods() > 0)
        HasOverridingMethodWithoutOverrideControl = true;
      // Check whether the explicitly-defaulted special members are valid.
      if (!M->isInvalidDecl() && M->isExplicitlyDefaulted())
        CheckExplicitlyDefaultedSpecialMember(M);

      // For an explicitly defaulted or deleted special member, we defer
      // determining triviality until the class is complete. That time is now!
      CXXSpecialMember CSM = getSpecialMember(M);
      if (!M->isImplicit() && !M->isUserProvided()) {
        if (CSM != CXXInvalid) {
          M->setTrivial(SpecialMemberIsTrivial(M, CSM));
          // Inform the class that we've finished declaring this member.
          Record->finishedDefaultedOrDeletedMember(M);
          M->setTrivialForCall(
              HasTrivialABI ||
              SpecialMemberIsTrivial(M, CSM, TAH_ConsiderTrivialABI));
          Record->setTrivialForCallFlags(M);
        }
      }

      // Set triviality for the purpose of calls if this is a user-provided
      // copy/move constructor or destructor.
      if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor ||
           CSM == CXXDestructor) && M->isUserProvided()) {
        M->setTrivialForCall(HasTrivialABI);
        Record->setTrivialForCallFlags(M);
      }

      if (!M->isInvalidDecl() && M->isExplicitlyDefaulted() &&
          M->hasAttr<DLLExportAttr>()) {
        if (getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015) &&
            M->isTrivial() &&
            (CSM == CXXDefaultConstructor || CSM == CXXCopyConstructor ||
             CSM == CXXDestructor))
          M->dropAttr<DLLExportAttr>();

        if (M->hasAttr<DLLExportAttr>()) {
          DefineImplicitSpecialMember(*this, M, M->getLocation());
          ActOnFinishInlineFunctionDef(M);
        }
      }
    }
  }

  if (HasMethodWithOverrideControl &&
      HasOverridingMethodWithoutOverrideControl) {
    // At least one method has the 'override' control declared.
    // Diagnose all other overridden methods which do not have 'override' specified on them.
    for (auto *M : Record->methods())
      DiagnoseAbsenceOfOverrideControl(M);
  }

  // ms_struct is a request to use the same ABI rules as MSVC.  Check
  // whether this class uses any C++ features that are implemented
  // completely differently in MSVC, and if so, emit a diagnostic.
  // That diagnostic defaults to an error, but we allow projects to
  // map it down to a warning (or ignore it).  It's a fairly common
  // practice among users of the ms_struct pragma to mass-annotate
  // headers, sweeping up a bunch of types that the project doesn't
  // really rely on MSVC-compatible layout for.  We must therefore
  // support "ms_struct except for C++ stuff" as a secondary ABI.
  if (Record->isMsStruct(Context) &&
      (Record->isPolymorphic() || Record->getNumBases())) {
    Diag(Record->getLocation(), diag::warn_cxx_ms_struct);
  }

  checkClassLevelDLLAttribute(Record);
  checkClassLevelCodeSegAttribute(Record);

  bool ClangABICompat4 =
      Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4;
  TargetInfo::CallingConvKind CCK =
      Context.getTargetInfo().getCallingConvKind(ClangABICompat4);
  bool CanPass = canPassInRegisters(*this, Record, CCK);

  // Do not change ArgPassingRestrictions if it has already been set to
  // APK_CanNeverPassInRegs.
  if (Record->getArgPassingRestrictions() != RecordDecl::APK_CanNeverPassInRegs)
    Record->setArgPassingRestrictions(CanPass
                                          ? RecordDecl::APK_CanPassInRegs
                                          : RecordDecl::APK_CannotPassInRegs);

  // If canPassInRegisters returns true despite the record having a non-trivial
  // destructor, the record is destructed in the callee. This happens only when
  // the record or one of its subobjects has a field annotated with trivial_abi
  // or a field qualified with ObjC __strong/__weak.
  if (Context.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee())
    Record->setParamDestroyedInCallee(true);
  else if (Record->hasNonTrivialDestructor())
    Record->setParamDestroyedInCallee(CanPass);

  if (getLangOpts().ForceEmitVTables) {
    // If we want to emit all the vtables, we need to mark it as used.  This
    // is especially required for cases like vtable assumption loads.
    MarkVTableUsed(Record->getInnerLocStart(), Record);
  }
}

/// Look up the special member function that would be called by a special
/// member function for a subobject of class type.
///
/// \param Class The class type of the subobject.
/// \param CSM The kind of special member function.
/// \param FieldQuals If the subobject is a field, its cv-qualifiers.
/// \param ConstRHS True if this is a copy operation with a const object
///        on its RHS, that is, if the argument to the outer special member
///        function is 'const' and this is not a field marked 'mutable'.
static Sema::SpecialMemberOverloadResult lookupCallFromSpecialMember(
    Sema &S, CXXRecordDecl *Class, Sema::CXXSpecialMember CSM,
    unsigned FieldQuals, bool ConstRHS) {
  unsigned LHSQuals = 0;
  if (CSM == Sema::CXXCopyAssignment || CSM == Sema::CXXMoveAssignment)
    LHSQuals = FieldQuals;

  unsigned RHSQuals = FieldQuals;
  if (CSM == Sema::CXXDefaultConstructor || CSM == Sema::CXXDestructor)
    RHSQuals = 0;
  else if (ConstRHS)
    RHSQuals |= Qualifiers::Const;

  return S.LookupSpecialMember(Class, CSM,
                               RHSQuals & Qualifiers::Const,
                               RHSQuals & Qualifiers::Volatile,
                               false,
                               LHSQuals & Qualifiers::Const,
                               LHSQuals & Qualifiers::Volatile);
}

class Sema::InheritedConstructorInfo {
  Sema &S;
  SourceLocation UseLoc;

  /// A mapping from the base classes through which the constructor was
  /// inherited to the using shadow declaration in that base class (or a null
  /// pointer if the constructor was declared in that base class).
  llvm::DenseMap<CXXRecordDecl *, ConstructorUsingShadowDecl *>
      InheritedFromBases;

public:
  InheritedConstructorInfo(Sema &S, SourceLocation UseLoc,
                           ConstructorUsingShadowDecl *Shadow)
      : S(S), UseLoc(UseLoc) {
    bool DiagnosedMultipleConstructedBases = false;
    CXXRecordDecl *ConstructedBase = nullptr;
    UsingDecl *ConstructedBaseUsing = nullptr;

    // Find the set of such base class subobjects and check that there's a
    // unique constructed subobject.
    for (auto *D : Shadow->redecls()) {
      auto *DShadow = cast<ConstructorUsingShadowDecl>(D);
      auto *DNominatedBase = DShadow->getNominatedBaseClass();
      auto *DConstructedBase = DShadow->getConstructedBaseClass();

      InheritedFromBases.insert(
          std::make_pair(DNominatedBase->getCanonicalDecl(),
                         DShadow->getNominatedBaseClassShadowDecl()));
      if (DShadow->constructsVirtualBase())
        InheritedFromBases.insert(
            std::make_pair(DConstructedBase->getCanonicalDecl(),
                           DShadow->getConstructedBaseClassShadowDecl()));
      else
        assert(DNominatedBase == DConstructedBase);

      // [class.inhctor.init]p2:
      //   If the constructor was inherited from multiple base class subobjects
      //   of type B, the program is ill-formed.
      if (!ConstructedBase) {
        ConstructedBase = DConstructedBase;
        ConstructedBaseUsing = D->getUsingDecl();
      } else if (ConstructedBase != DConstructedBase &&
                 !Shadow->isInvalidDecl()) {
        if (!DiagnosedMultipleConstructedBases) {
          S.Diag(UseLoc, diag::err_ambiguous_inherited_constructor)
              << Shadow->getTargetDecl();
          S.Diag(ConstructedBaseUsing->getLocation(),
               diag::note_ambiguous_inherited_constructor_using)
              << ConstructedBase;
          DiagnosedMultipleConstructedBases = true;
        }
        S.Diag(D->getUsingDecl()->getLocation(),
               diag::note_ambiguous_inherited_constructor_using)
            << DConstructedBase;
      }
    }

    if (DiagnosedMultipleConstructedBases)
      Shadow->setInvalidDecl();
  }

  /// Find the constructor to use for inherited construction of a base class,
  /// and whether that base class constructor inherits the constructor from a
  /// virtual base class (in which case it won't actually invoke it).
  std::pair<CXXConstructorDecl *, bool>
  findConstructorForBase(CXXRecordDecl *Base, CXXConstructorDecl *Ctor) const {
    auto It = InheritedFromBases.find(Base->getCanonicalDecl());
    if (It == InheritedFromBases.end())
      return std::make_pair(nullptr, false);

    // This is an intermediary class.
    if (It->second)
      return std::make_pair(
          S.findInheritingConstructor(UseLoc, Ctor, It->second),
          It->second->constructsVirtualBase());

    // This is the base class from which the constructor was inherited.
    return std::make_pair(Ctor, false);
  }
};

/// Is the special member function which would be selected to perform the
/// specified operation on the specified class type a constexpr constructor?
static bool
specialMemberIsConstexpr(Sema &S, CXXRecordDecl *ClassDecl,
                         Sema::CXXSpecialMember CSM, unsigned Quals,
                         bool ConstRHS,
                         CXXConstructorDecl *InheritedCtor = nullptr,
                         Sema::InheritedConstructorInfo *Inherited = nullptr) {
  // If we're inheriting a constructor, see if we need to call it for this base
  // class.
  if (InheritedCtor) {
    assert(CSM == Sema::CXXDefaultConstructor);
    auto BaseCtor =
        Inherited->findConstructorForBase(ClassDecl, InheritedCtor).first;
    if (BaseCtor)
      return BaseCtor->isConstexpr();
  }

  if (CSM == Sema::CXXDefaultConstructor)
    return ClassDecl->hasConstexprDefaultConstructor();

  Sema::SpecialMemberOverloadResult SMOR =
      lookupCallFromSpecialMember(S, ClassDecl, CSM, Quals, ConstRHS);
  if (!SMOR.getMethod())
    // A constructor we wouldn't select can't be "involved in initializing"
    // anything.
    return true;
  return SMOR.getMethod()->isConstexpr();
}

/// Determine whether the specified special member function would be constexpr
/// if it were implicitly defined.
static bool defaultedSpecialMemberIsConstexpr(
    Sema &S, CXXRecordDecl *ClassDecl, Sema::CXXSpecialMember CSM,
    bool ConstArg, CXXConstructorDecl *InheritedCtor = nullptr,
    Sema::InheritedConstructorInfo *Inherited = nullptr) {
  if (!S.getLangOpts().CPlusPlus11)
    return false;

  // C++11 [dcl.constexpr]p4:
  // In the definition of a constexpr constructor [...]
  bool Ctor = true;
  switch (CSM) {
  case Sema::CXXDefaultConstructor:
    if (Inherited)
      break;
    // Since default constructor lookup is essentially trivial (and cannot
    // involve, for instance, template instantiation), we compute whether a
    // defaulted default constructor is constexpr directly within CXXRecordDecl.
    //
    // This is important for performance; we need to know whether the default
    // constructor is constexpr to determine whether the type is a literal type.
    return ClassDecl->defaultedDefaultConstructorIsConstexpr();

  case Sema::CXXCopyConstructor:
  case Sema::CXXMoveConstructor:
    // For copy or move constructors, we need to perform overload resolution.
    break;

  case Sema::CXXCopyAssignment:
  case Sema::CXXMoveAssignment:
    if (!S.getLangOpts().CPlusPlus14)
      return false;
    // In C++1y, we need to perform overload resolution.
    Ctor = false;
    break;

  case Sema::CXXDestructor:
  case Sema::CXXInvalid:
    return false;
  }

  //   -- if the class is a non-empty union, or for each non-empty anonymous
  //      union member of a non-union class, exactly one non-static data member
  //      shall be initialized; [DR1359]
  //
  // If we squint, this is guaranteed, since exactly one non-static data member
  // will be initialized (if the constructor isn't deleted), we just don't know
  // which one.
  if (Ctor && ClassDecl->isUnion())
    return CSM == Sema::CXXDefaultConstructor
               ? ClassDecl->hasInClassInitializer() ||
                     !ClassDecl->hasVariantMembers()
               : true;

  //   -- the class shall not have any virtual base classes;
  if (Ctor && ClassDecl->getNumVBases())
    return false;

  // C++1y [class.copy]p26:
  //   -- [the class] is a literal type, and
  if (!Ctor && !ClassDecl->isLiteral())
    return false;

  //   -- every constructor involved in initializing [...] base class
  //      sub-objects shall be a constexpr constructor;
  //   -- the assignment operator selected to copy/move each direct base
  //      class is a constexpr function, and
  for (const auto &B : ClassDecl->bases()) {
    const RecordType *BaseType = B.getType()->getAs<RecordType>();
    if (!BaseType) continue;

    CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
    if (!specialMemberIsConstexpr(S, BaseClassDecl, CSM, 0, ConstArg,
                                  InheritedCtor, Inherited))
      return false;
  }

  //   -- every constructor involved in initializing non-static data members
  //      [...] shall be a constexpr constructor;
  //   -- every non-static data member and base class sub-object shall be
  //      initialized
  //   -- for each non-static data member of X that is of class type (or array
  //      thereof), the assignment operator selected to copy/move that member is
  //      a constexpr function
  for (const auto *F : ClassDecl->fields()) {
    if (F->isInvalidDecl())
      continue;
    if (CSM == Sema::CXXDefaultConstructor && F->hasInClassInitializer())
      continue;
    QualType BaseType = S.Context.getBaseElementType(F->getType());
    if (const RecordType *RecordTy = BaseType->getAs<RecordType>()) {
      CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
      if (!specialMemberIsConstexpr(S, FieldRecDecl, CSM,
                                    BaseType.getCVRQualifiers(),
                                    ConstArg && !F->isMutable()))
        return false;
    } else if (CSM == Sema::CXXDefaultConstructor) {
      return false;
    }
  }

  // All OK, it's constexpr!
  return true;
}

static Sema::ImplicitExceptionSpecification
ComputeDefaultedSpecialMemberExceptionSpec(
    Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM,
    Sema::InheritedConstructorInfo *ICI);

static Sema::ImplicitExceptionSpecification
computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) {
  auto CSM = S.getSpecialMember(MD);
  if (CSM != Sema::CXXInvalid)
    return ComputeDefaultedSpecialMemberExceptionSpec(S, Loc, MD, CSM, nullptr);

  auto *CD = cast<CXXConstructorDecl>(MD);
  assert(CD->getInheritedConstructor() &&
         "only special members have implicit exception specs");
  Sema::InheritedConstructorInfo ICI(
      S, Loc, CD->getInheritedConstructor().getShadowDecl());
  return ComputeDefaultedSpecialMemberExceptionSpec(
      S, Loc, CD, Sema::CXXDefaultConstructor, &ICI);
}

static FunctionProtoType::ExtProtoInfo getImplicitMethodEPI(Sema &S,
                                                            CXXMethodDecl *MD) {
  FunctionProtoType::ExtProtoInfo EPI;

  // Build an exception specification pointing back at this member.
  EPI.ExceptionSpec.Type = EST_Unevaluated;
  EPI.ExceptionSpec.SourceDecl = MD;

  // Set the calling convention to the default for C++ instance methods.
  EPI.ExtInfo = EPI.ExtInfo.withCallingConv(
      S.Context.getDefaultCallingConvention(/*IsVariadic=*/false,
                                            /*IsCXXMethod=*/true));
  return EPI;
}

void Sema::EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD) {
  const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
  if (FPT->getExceptionSpecType() != EST_Unevaluated)
    return;

  // Evaluate the exception specification.
  auto IES = computeImplicitExceptionSpec(*this, Loc, MD);
  auto ESI = IES.getExceptionSpec();

  // Update the type of the special member to use it.
  UpdateExceptionSpec(MD, ESI);

  // A user-provided destructor can be defined outside the class. When that
  // happens, be sure to update the exception specification on both
  // declarations.
  const FunctionProtoType *CanonicalFPT =
    MD->getCanonicalDecl()->getType()->castAs<FunctionProtoType>();
  if (CanonicalFPT->getExceptionSpecType() == EST_Unevaluated)
    UpdateExceptionSpec(MD->getCanonicalDecl(), ESI);
}

void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) {
  CXXRecordDecl *RD = MD->getParent();
  CXXSpecialMember CSM = getSpecialMember(MD);

  assert(MD->isExplicitlyDefaulted() && CSM != CXXInvalid &&
         "not an explicitly-defaulted special member");

  // Whether this was the first-declared instance of the constructor.
  // This affects whether we implicitly add an exception spec and constexpr.
  bool First = MD == MD->getCanonicalDecl();

  bool HadError = false;

  // C++11 [dcl.fct.def.default]p1:
  //   A function that is explicitly defaulted shall
  //     -- be a special member function (checked elsewhere),
  //     -- have the same type (except for ref-qualifiers, and except that a
  //        copy operation can take a non-const reference) as an implicit
  //        declaration, and
  //     -- not have default arguments.
  // C++2a changes the second bullet to instead delete the function if it's
  // defaulted on its first declaration, unless it's "an assignment operator,
  // and its return type differs or its parameter type is not a reference".
  bool DeleteOnTypeMismatch = getLangOpts().CPlusPlus2a && First;
  bool ShouldDeleteForTypeMismatch = false;
  unsigned ExpectedParams = 1;
  if (CSM == CXXDefaultConstructor || CSM == CXXDestructor)
    ExpectedParams = 0;
  if (MD->getNumParams() != ExpectedParams) {
    // This checks for default arguments: a copy or move constructor with a
    // default argument is classified as a default constructor, and assignment
    // operations and destructors can't have default arguments.
    Diag(MD->getLocation(), diag::err_defaulted_special_member_params)
      << CSM << MD->getSourceRange();
    HadError = true;
  } else if (MD->isVariadic()) {
    if (DeleteOnTypeMismatch)
      ShouldDeleteForTypeMismatch = true;
    else {
      Diag(MD->getLocation(), diag::err_defaulted_special_member_variadic)
        << CSM << MD->getSourceRange();
      HadError = true;
    }
  }

  const FunctionProtoType *Type = MD->getType()->getAs<FunctionProtoType>();

  bool CanHaveConstParam = false;
  if (CSM == CXXCopyConstructor)
    CanHaveConstParam = RD->implicitCopyConstructorHasConstParam();
  else if (CSM == CXXCopyAssignment)
    CanHaveConstParam = RD->implicitCopyAssignmentHasConstParam();

  QualType ReturnType = Context.VoidTy;
  if (CSM == CXXCopyAssignment || CSM == CXXMoveAssignment) {
    // Check for return type matching.
    ReturnType = Type->getReturnType();

    QualType DeclType = Context.getTypeDeclType(RD);
    DeclType = Context.getAddrSpaceQualType(DeclType, MD->getMethodQualifiers().getAddressSpace());
    QualType ExpectedReturnType = Context.getLValueReferenceType(DeclType);

    if (!Context.hasSameType(ReturnType, ExpectedReturnType)) {
      Diag(MD->getLocation(), diag::err_defaulted_special_member_return_type)
        << (CSM == CXXMoveAssignment) << ExpectedReturnType;
      HadError = true;
    }

    // A defaulted special member cannot have cv-qualifiers.
    if (Type->getMethodQuals().hasConst() || Type->getMethodQuals().hasVolatile()) {
      if (DeleteOnTypeMismatch)
        ShouldDeleteForTypeMismatch = true;
      else {
        Diag(MD->getLocation(), diag::err_defaulted_special_member_quals)
          << (CSM == CXXMoveAssignment) << getLangOpts().CPlusPlus14;
        HadError = true;
      }
    }
  }

  // Check for parameter type matching.
  QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType();
  bool HasConstParam = false;
  if (ExpectedParams && ArgType->isReferenceType()) {
    // Argument must be reference to possibly-const T.
    QualType ReferentType = ArgType->getPointeeType();
    HasConstParam = ReferentType.isConstQualified();

    if (ReferentType.isVolatileQualified()) {
      if (DeleteOnTypeMismatch)
        ShouldDeleteForTypeMismatch = true;
      else {
        Diag(MD->getLocation(),
             diag::err_defaulted_special_member_volatile_param) << CSM;
        HadError = true;
      }
    }

    if (HasConstParam && !CanHaveConstParam) {
      if (DeleteOnTypeMismatch)
        ShouldDeleteForTypeMismatch = true;
      else if (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment) {
        Diag(MD->getLocation(),
             diag::err_defaulted_special_member_copy_const_param)
          << (CSM == CXXCopyAssignment);
        // FIXME: Explain why this special member can't be const.
        HadError = true;
      } else {
        Diag(MD->getLocation(),
             diag::err_defaulted_special_member_move_const_param)
          << (CSM == CXXMoveAssignment);
        HadError = true;
      }
    }
  } else if (ExpectedParams) {
    // A copy assignment operator can take its argument by value, but a
    // defaulted one cannot.
    assert(CSM == CXXCopyAssignment && "unexpected non-ref argument");
    Diag(MD->getLocation(), diag::err_defaulted_copy_assign_not_ref);
    HadError = true;
  }

  // C++11 [dcl.fct.def.default]p2:
  //   An explicitly-defaulted function may be declared constexpr only if it
  //   would have been implicitly declared as constexpr,
  // Do not apply this rule to members of class templates, since core issue 1358
  // makes such functions always instantiate to constexpr functions. For
  // functions which cannot be constexpr (for non-constructors in C++11 and for
  // destructors in C++1y), this is checked elsewhere.
  //
  // FIXME: This should not apply if the member is deleted.
  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM,
                                                     HasConstParam);
  if ((getLangOpts().CPlusPlus14 ? !isa<CXXDestructorDecl>(MD)
                                 : isa<CXXConstructorDecl>(MD)) &&
      MD->isConstexpr() && !Constexpr &&
      MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
    Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM;
    // FIXME: Explain why the special member can't be constexpr.
    HadError = true;
  }

  if (First) {
    // C++2a [dcl.fct.def.default]p3:
    //   If a function is explicitly defaulted on its first declaration, it is
    //   implicitly considered to be constexpr if the implicit declaration
    //   would be.
    MD->setConstexpr(Constexpr);

    if (!Type->hasExceptionSpec()) {
      // C++2a [except.spec]p3:
      //   If a declaration of a function does not have a noexcept-specifier
      //   [and] is defaulted on its first declaration, [...] the exception
      //   specification is as specified below
      FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
      EPI.ExceptionSpec.Type = EST_Unevaluated;
      EPI.ExceptionSpec.SourceDecl = MD;
      MD->setType(Context.getFunctionType(ReturnType,
                                          llvm::makeArrayRef(&ArgType,
                                                             ExpectedParams),
                                          EPI));
    }
  }

  if (ShouldDeleteForTypeMismatch || ShouldDeleteSpecialMember(MD, CSM)) {
    if (First) {
      SetDeclDeleted(MD, MD->getLocation());
      if (!inTemplateInstantiation() && !HadError) {
        Diag(MD->getLocation(), diag::warn_defaulted_method_deleted) << CSM;
        if (ShouldDeleteForTypeMismatch) {
          Diag(MD->getLocation(), diag::note_deleted_type_mismatch) << CSM;
        } else {
          ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
        }
      }
      if (ShouldDeleteForTypeMismatch && !HadError) {
        Diag(MD->getLocation(),
             diag::warn_cxx17_compat_defaulted_method_type_mismatch) << CSM;
      }
    } else {
      // C++11 [dcl.fct.def.default]p4:
      //   [For a] user-provided explicitly-defaulted function [...] if such a
      //   function is implicitly defined as deleted, the program is ill-formed.
      Diag(MD->getLocation(), diag::err_out_of_line_default_deletes) << CSM;
      assert(!ShouldDeleteForTypeMismatch && "deleted non-first decl");
      ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
      HadError = true;
    }
  }

  if (HadError)
    MD->setInvalidDecl();
}

void Sema::CheckDelayedMemberExceptionSpecs() {
  decltype(DelayedOverridingExceptionSpecChecks) Overriding;
  decltype(DelayedEquivalentExceptionSpecChecks) Equivalent;

  std::swap(Overriding, DelayedOverridingExceptionSpecChecks);
  std::swap(Equivalent, DelayedEquivalentExceptionSpecChecks);

  // Perform any deferred checking of exception specifications for virtual
  // destructors.
  for (auto &Check : Overriding)
    CheckOverridingFunctionExceptionSpec(Check.first, Check.second);

  // Perform any deferred checking of exception specifications for befriended
  // special members.
  for (auto &Check : Equivalent)
    CheckEquivalentExceptionSpec(Check.second, Check.first);
}

namespace {
/// CRTP base class for visiting operations performed by a special member
/// function (or inherited constructor).
template<typename Derived>
struct SpecialMemberVisitor {
  Sema &S;
  CXXMethodDecl *MD;
  Sema::CXXSpecialMember CSM;
  Sema::InheritedConstructorInfo *ICI;

  // Properties of the special member, computed for convenience.
  bool IsConstructor = false, IsAssignment = false, ConstArg = false;

  SpecialMemberVisitor(Sema &S, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM,
                       Sema::InheritedConstructorInfo *ICI)
      : S(S), MD(MD), CSM(CSM), ICI(ICI) {
    switch (CSM) {
    case Sema::CXXDefaultConstructor:
    case Sema::CXXCopyConstructor:
    case Sema::CXXMoveConstructor:
      IsConstructor = true;
      break;
    case Sema::CXXCopyAssignment:
    case Sema::CXXMoveAssignment:
      IsAssignment = true;
      break;
    case Sema::CXXDestructor:
      break;
    case Sema::CXXInvalid:
      llvm_unreachable("invalid special member kind");
    }

    if (MD->getNumParams()) {
      if (const ReferenceType *RT =
              MD->getParamDecl(0)->getType()->getAs<ReferenceType>())
        ConstArg = RT->getPointeeType().isConstQualified();
    }
  }

  Derived &getDerived() { return static_cast<Derived&>(*this); }

  /// Is this a "move" special member?
  bool isMove() const {
    return CSM == Sema::CXXMoveConstructor || CSM == Sema::CXXMoveAssignment;
  }

  /// Look up the corresponding special member in the given class.
  Sema::SpecialMemberOverloadResult lookupIn(CXXRecordDecl *Class,
                                             unsigned Quals, bool IsMutable) {
    return lookupCallFromSpecialMember(S, Class, CSM, Quals,
                                       ConstArg && !IsMutable);
  }

  /// Look up the constructor for the specified base class to see if it's
  /// overridden due to this being an inherited constructor.
  Sema::SpecialMemberOverloadResult lookupInheritedCtor(CXXRecordDecl *Class) {
    if (!ICI)
      return {};
    assert(CSM == Sema::CXXDefaultConstructor);
    auto *BaseCtor =
      cast<CXXConstructorDecl>(MD)->getInheritedConstructor().getConstructor();
    if (auto *MD = ICI->findConstructorForBase(Class, BaseCtor).first)
      return MD;
    return {};
  }

  /// A base or member subobject.
  typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject;

  /// Get the location to use for a subobject in diagnostics.
  static SourceLocation getSubobjectLoc(Subobject Subobj) {
    // FIXME: For an indirect virtual base, the direct base leading to
    // the indirect virtual base would be a more useful choice.
    if (auto *B = Subobj.dyn_cast<CXXBaseSpecifier*>())
      return B->getBaseTypeLoc();
    else
      return Subobj.get<FieldDecl*>()->getLocation();
  }

  enum BasesToVisit {
    /// Visit all non-virtual (direct) bases.
    VisitNonVirtualBases,
    /// Visit all direct bases, virtual or not.
    VisitDirectBases,
    /// Visit all non-virtual bases, and all virtual bases if the class
    /// is not abstract.
    VisitPotentiallyConstructedBases,
    /// Visit all direct or virtual bases.
    VisitAllBases
  };

  // Visit the bases and members of the class.
  bool visit(BasesToVisit Bases) {
    CXXRecordDecl *RD = MD->getParent();

    if (Bases == VisitPotentiallyConstructedBases)
      Bases = RD->isAbstract() ? VisitNonVirtualBases : VisitAllBases;

    for (auto &B : RD->bases())
      if ((Bases == VisitDirectBases || !B.isVirtual()) &&
          getDerived().visitBase(&B))
        return true;

    if (Bases == VisitAllBases)
      for (auto &B : RD->vbases())
        if (getDerived().visitBase(&B))
          return true;

    for (auto *F : RD->fields())
      if (!F->isInvalidDecl() && !F->isUnnamedBitfield() &&
          getDerived().visitField(F))
        return true;

    return false;
  }
};
}

namespace {
struct SpecialMemberDeletionInfo
    : SpecialMemberVisitor<SpecialMemberDeletionInfo> {
  bool Diagnose;

  SourceLocation Loc;

  bool AllFieldsAreConst;

  SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD,
                            Sema::CXXSpecialMember CSM,
                            Sema::InheritedConstructorInfo *ICI, bool Diagnose)
      : SpecialMemberVisitor(S, MD, CSM, ICI), Diagnose(Diagnose),
        Loc(MD->getLocation()), AllFieldsAreConst(true) {}

  bool inUnion() const { return MD->getParent()->isUnion(); }

  Sema::CXXSpecialMember getEffectiveCSM() {
    return ICI ? Sema::CXXInvalid : CSM;
  }

  bool shouldDeleteForVariantObjCPtrMember(FieldDecl *FD, QualType FieldType);

  bool visitBase(CXXBaseSpecifier *Base) { return shouldDeleteForBase(Base); }
  bool visitField(FieldDecl *Field) { return shouldDeleteForField(Field); }

  bool shouldDeleteForBase(CXXBaseSpecifier *Base);
  bool shouldDeleteForField(FieldDecl *FD);
  bool shouldDeleteForAllConstMembers();

  bool shouldDeleteForClassSubobject(CXXRecordDecl *Class, Subobject Subobj,
                                     unsigned Quals);
  bool shouldDeleteForSubobjectCall(Subobject Subobj,
                                    Sema::SpecialMemberOverloadResult SMOR,
                                    bool IsDtorCallInCtor);

  bool isAccessible(Subobject Subobj, CXXMethodDecl *D);
};
}

/// Is the given special member inaccessible when used on the given
/// sub-object.
bool SpecialMemberDeletionInfo::isAccessible(Subobject Subobj,
                                             CXXMethodDecl *target) {
  /// If we're operating on a base class, the object type is the
  /// type of this special member.
  QualType objectTy;
  AccessSpecifier access = target->getAccess();
  if (CXXBaseSpecifier *base = Subobj.dyn_cast<CXXBaseSpecifier*>()) {
    objectTy = S.Context.getTypeDeclType(MD->getParent());
    access = CXXRecordDecl::MergeAccess(base->getAccessSpecifier(), access);

  // If we're operating on a field, the object type is the type of the field.
  } else {
    objectTy = S.Context.getTypeDeclType(target->getParent());
  }

  return S.isSpecialMemberAccessibleForDeletion(target, access, objectTy);
}

/// Check whether we should delete a special member due to the implicit
/// definition containing a call to a special member of a subobject.
bool SpecialMemberDeletionInfo::shouldDeleteForSubobjectCall(
    Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR,
    bool IsDtorCallInCtor) {
  CXXMethodDecl *Decl = SMOR.getMethod();
  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();

  int DiagKind = -1;

  if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted)
    DiagKind = !Decl ? 0 : 1;
  else if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
    DiagKind = 2;
  else if (!isAccessible(Subobj, Decl))
    DiagKind = 3;
  else if (!IsDtorCallInCtor && Field && Field->getParent()->isUnion() &&
           !Decl->isTrivial()) {
    // A member of a union must have a trivial corresponding special member.
    // As a weird special case, a destructor call from a union's constructor
    // must be accessible and non-deleted, but need not be trivial. Such a
    // destructor is never actually called, but is semantically checked as
    // if it were.
    DiagKind = 4;
  }

  if (DiagKind == -1)
    return false;

  if (Diagnose) {
    if (Field) {
      S.Diag(Field->getLocation(),
             diag::note_deleted_special_member_class_subobject)
        << getEffectiveCSM() << MD->getParent() << /*IsField*/true
        << Field << DiagKind << IsDtorCallInCtor << /*IsObjCPtr*/false;
    } else {
      CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>();
      S.Diag(Base->getBeginLoc(),
             diag::note_deleted_special_member_class_subobject)
          << getEffectiveCSM() << MD->getParent() << /*IsField*/ false
          << Base->getType() << DiagKind << IsDtorCallInCtor
          << /*IsObjCPtr*/false;
    }

    if (DiagKind == 1)
      S.NoteDeletedFunction(Decl);
    // FIXME: Explain inaccessibility if DiagKind == 3.
  }

  return true;
}

/// Check whether we should delete a special member function due to having a
/// direct or virtual base class or non-static data member of class type M.
bool SpecialMemberDeletionInfo::shouldDeleteForClassSubobject(
    CXXRecordDecl *Class, Subobject Subobj, unsigned Quals) {
  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
  bool IsMutable = Field && Field->isMutable();

  // C++11 [class.ctor]p5:
  // -- any direct or virtual base class, or non-static data member with no
  //    brace-or-equal-initializer, has class type M (or array thereof) and
  //    either M has no default constructor or overload resolution as applied
  //    to M's default constructor results in an ambiguity or in a function
  //    that is deleted or inaccessible
  // C++11 [class.copy]p11, C++11 [class.copy]p23:
  // -- a direct or virtual base class B that cannot be copied/moved because
  //    overload resolution, as applied to B's corresponding special member,
  //    results in an ambiguity or a function that is deleted or inaccessible
  //    from the defaulted special member
  // C++11 [class.dtor]p5:
  // -- any direct or virtual base class [...] has a type with a destructor
  //    that is deleted or inaccessible
  if (!(CSM == Sema::CXXDefaultConstructor &&
        Field && Field->hasInClassInitializer()) &&
      shouldDeleteForSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable),
                                   false))
    return true;

  // C++11 [class.ctor]p5, C++11 [class.copy]p11:
  // -- any direct or virtual base class or non-static data member has a
  //    type with a destructor that is deleted or inaccessible
  if (IsConstructor) {
    Sema::SpecialMemberOverloadResult SMOR =
        S.LookupSpecialMember(Class, Sema::CXXDestructor,
                              false, false, false, false, false);
    if (shouldDeleteForSubobjectCall(Subobj, SMOR, true))
      return true;
  }

  return false;
}

bool SpecialMemberDeletionInfo::shouldDeleteForVariantObjCPtrMember(
    FieldDecl *FD, QualType FieldType) {
  // The defaulted special functions are defined as deleted if this is a variant
  // member with a non-trivial ownership type, e.g., ObjC __strong or __weak
  // type under ARC.
  if (!FieldType.hasNonTrivialObjCLifetime())
    return false;

  // Don't make the defaulted default constructor defined as deleted if the
  // member has an in-class initializer.
  if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer())
    return false;

  if (Diagnose) {
    auto *ParentClass = cast<CXXRecordDecl>(FD->getParent());
    S.Diag(FD->getLocation(),
           diag::note_deleted_special_member_class_subobject)
        << getEffectiveCSM() << ParentClass << /*IsField*/true
        << FD << 4 << /*IsDtorCallInCtor*/false << /*IsObjCPtr*/true;
  }

  return true;
}

/// Check whether we should delete a special member function due to the class
/// having a particular direct or virtual base class.
bool SpecialMemberDeletionInfo::shouldDeleteForBase(CXXBaseSpecifier *Base) {
  CXXRecordDecl *BaseClass = Base->getType()->getAsCXXRecordDecl();
  // If program is correct, BaseClass cannot be null, but if it is, the error
  // must be reported elsewhere.
  if (!BaseClass)
    return false;
  // If we have an inheriting constructor, check whether we're calling an
  // inherited constructor instead of a default constructor.
  Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass);
  if (auto *BaseCtor = SMOR.getMethod()) {
    // Note that we do not check access along this path; other than that,
    // this is the same as shouldDeleteForSubobjectCall(Base, BaseCtor, false);
    // FIXME: Check that the base has a usable destructor! Sink this into
    // shouldDeleteForClassSubobject.
    if (BaseCtor->isDeleted() && Diagnose) {
      S.Diag(Base->getBeginLoc(),
             diag::note_deleted_special_member_class_subobject)
          << getEffectiveCSM() << MD->getParent() << /*IsField*/ false
          << Base->getType() << /*Deleted*/ 1 << /*IsDtorCallInCtor*/ false
          << /*IsObjCPtr*/false;
      S.NoteDeletedFunction(BaseCtor);
    }
    return BaseCtor->isDeleted();
  }
  return shouldDeleteForClassSubobject(BaseClass, Base, 0);
}

/// Check whether we should delete a special member function due to the class
/// having a particular non-static data member.
bool SpecialMemberDeletionInfo::shouldDeleteForField(FieldDecl *FD) {
  QualType FieldType = S.Context.getBaseElementType(FD->getType());
  CXXRecordDecl *FieldRecord = FieldType->getAsCXXRecordDecl();

  if (inUnion() && shouldDeleteForVariantObjCPtrMember(FD, FieldType))
    return true;

  if (CSM == Sema::CXXDefaultConstructor) {
    // For a default constructor, all references must be initialized in-class
    // and, if a union, it must have a non-const member.
    if (FieldType->isReferenceType() && !FD->hasInClassInitializer()) {
      if (Diagnose)
        S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
          << !!ICI << MD->getParent() << FD << FieldType << /*Reference*/0;
      return true;
    }
    // C++11 [class.ctor]p5: any non-variant non-static data member of
    // const-qualified type (or array thereof) with no
    // brace-or-equal-initializer does not have a user-provided default
    // constructor.
    if (!inUnion() && FieldType.isConstQualified() &&
        !FD->hasInClassInitializer() &&
        (!FieldRecord || !FieldRecord->hasUserProvidedDefaultConstructor())) {
      if (Diagnose)
        S.Diag(FD->getLocation(), diag::note_deleted_default_ctor_uninit_field)
          << !!ICI << MD->getParent() << FD << FD->getType() << /*Const*/1;
      return true;
    }

    if (inUnion() && !FieldType.isConstQualified())
      AllFieldsAreConst = false;
  } else if (CSM == Sema::CXXCopyConstructor) {
    // For a copy constructor, data members must not be of rvalue reference
    // type.
    if (FieldType->isRValueReferenceType()) {
      if (Diagnose)
        S.Diag(FD->getLocation(), diag::note_deleted_copy_ctor_rvalue_reference)
          << MD->getParent() << FD << FieldType;
      return true;
    }
  } else if (IsAssignment) {
    // For an assignment operator, data members must not be of reference type.
    if (FieldType->isReferenceType()) {
      if (Diagnose)
        S.Diag(FD->getLocation(), diag::note_deleted_assign_field)
          << isMove() << MD->getParent() << FD << FieldType << /*Reference*/0;
      return true;
    }
    if (!FieldRecord && FieldType.isConstQualified()) {
      // C++11 [class.copy]p23:
      // -- a non-static data member of const non-class type (or array thereof)
      if (Diagnose)
        S.Diag(FD->getLocation(), diag::note_deleted_assign_field)
          << isMove() << MD->getParent() << FD << FD->getType() << /*Const*/1;
      return true;
    }
  }

  if (FieldRecord) {
    // Some additional restrictions exist on the variant members.
    if (!inUnion() && FieldRecord->isUnion() &&
        FieldRecord->isAnonymousStructOrUnion()) {
      bool AllVariantFieldsAreConst = true;

      // FIXME: Handle anonymous unions declared within anonymous unions.
      for (auto *UI : FieldRecord->fields()) {
        QualType UnionFieldType = S.Context.getBaseElementType(UI->getType());

        if (shouldDeleteForVariantObjCPtrMember(&*UI, UnionFieldType))
          return true;

        if (!UnionFieldType.isConstQualified())
          AllVariantFieldsAreConst = false;

        CXXRecordDecl *UnionFieldRecord = UnionFieldType->getAsCXXRecordDecl();
        if (UnionFieldRecord &&
            shouldDeleteForClassSubobject(UnionFieldRecord, UI,
                                          UnionFieldType.getCVRQualifiers()))
          return true;
      }

      // At least one member in each anonymous union must be non-const
      if (CSM == Sema::CXXDefaultConstructor && AllVariantFieldsAreConst &&
          !FieldRecord->field_empty()) {
        if (Diagnose)
          S.Diag(FieldRecord->getLocation(),
                 diag::note_deleted_default_ctor_all_const)
            << !!ICI << MD->getParent() << /*anonymous union*/1;
        return true;
      }

      // Don't check the implicit member of the anonymous union type.
      // This is technically non-conformant, but sanity demands it.
      return false;
    }

    if (shouldDeleteForClassSubobject(FieldRecord, FD,
                                      FieldType.getCVRQualifiers()))
      return true;
  }

  return false;
}

/// C++11 [class.ctor] p5:
///   A defaulted default constructor for a class X is defined as deleted if
/// X is a union and all of its variant members are of const-qualified type.
bool SpecialMemberDeletionInfo::shouldDeleteForAllConstMembers() {
  // This is a silly definition, because it gives an empty union a deleted
  // default constructor. Don't do that.
  if (CSM == Sema::CXXDefaultConstructor && inUnion() && AllFieldsAreConst) {
    bool AnyFields = false;
    for (auto *F : MD->getParent()->fields())
      if ((AnyFields = !F->isUnnamedBitfield()))
        break;
    if (!AnyFields)
      return false;
    if (Diagnose)
      S.Diag(MD->getParent()->getLocation(),
             diag::note_deleted_default_ctor_all_const)
        << !!ICI << MD->getParent() << /*not anonymous union*/0;
    return true;
  }
  return false;
}

/// Determine whether a defaulted special member function should be defined as
/// deleted, as specified in C++11 [class.ctor]p5, C++11 [class.copy]p11,
/// C++11 [class.copy]p23, and C++11 [class.dtor]p5.
bool Sema::ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM,
                                     InheritedConstructorInfo *ICI,
                                     bool Diagnose) {
  if (MD->isInvalidDecl())
    return false;
  CXXRecordDecl *RD = MD->getParent();
  assert(!RD->isDependentType() && "do deletion after instantiation");
  if (!LangOpts.CPlusPlus11 || RD->isInvalidDecl())
    return false;

  // C++11 [expr.lambda.prim]p19:
  //   The closure type associated with a lambda-expression has a
  //   deleted (8.4.3) default constructor and a deleted copy
  //   assignment operator.
  // C++2a adds back these operators if the lambda has no capture-default.
  if (RD->isLambda() && !RD->lambdaIsDefaultConstructibleAndAssignable() &&
      (CSM == CXXDefaultConstructor || CSM == CXXCopyAssignment)) {
    if (Diagnose)
      Diag(RD->getLocation(), diag::note_lambda_decl);
    return true;
  }

  // For an anonymous struct or union, the copy and assignment special members
  // will never be used, so skip the check. For an anonymous union declared at
  // namespace scope, the constructor and destructor are used.
  if (CSM != CXXDefaultConstructor && CSM != CXXDestructor &&
      RD->isAnonymousStructOrUnion())
    return false;

  // C++11 [class.copy]p7, p18:
  //   If the class definition declares a move constructor or move assignment
  //   operator, an implicitly declared copy constructor or copy assignment
  //   operator is defined as deleted.
  if (MD->isImplicit() &&
      (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment)) {
    CXXMethodDecl *UserDeclaredMove = nullptr;

    // In Microsoft mode up to MSVC 2013, a user-declared move only causes the
    // deletion of the corresponding copy operation, not both copy operations.
    // MSVC 2015 has adopted the standards conforming behavior.
    bool DeletesOnlyMatchingCopy =
        getLangOpts().MSVCCompat &&
        !getLangOpts().isCompatibleWithMSVC(LangOptions::MSVC2015);

    if (RD->hasUserDeclaredMoveConstructor() &&
        (!DeletesOnlyMatchingCopy || CSM == CXXCopyConstructor)) {
      if (!Diagnose) return true;

      // Find any user-declared move constructor.
      for (auto *I : RD->ctors()) {
        if (I->isMoveConstructor()) {
          UserDeclaredMove = I;
          break;
        }
      }
      assert(UserDeclaredMove);
    } else if (RD->hasUserDeclaredMoveAssignment() &&
               (!DeletesOnlyMatchingCopy || CSM == CXXCopyAssignment)) {
      if (!Diagnose) return true;

      // Find any user-declared move assignment operator.
      for (auto *I : RD->methods()) {
        if (I->isMoveAssignmentOperator()) {
          UserDeclaredMove = I;
          break;
        }
      }
      assert(UserDeclaredMove);
    }

    if (UserDeclaredMove) {
      Diag(UserDeclaredMove->getLocation(),
           diag::note_deleted_copy_user_declared_move)
        << (CSM == CXXCopyAssignment) << RD
        << UserDeclaredMove->isMoveAssignmentOperator();
      return true;
    }
  }

  // Do access control from the special member function
  ContextRAII MethodContext(*this, MD);

  // C++11 [class.dtor]p5:
  // -- for a virtual destructor, lookup of the non-array deallocation function
  //    results in an ambiguity or in a function that is deleted or inaccessible
  if (CSM == CXXDestructor && MD->isVirtual()) {
    FunctionDecl *OperatorDelete = nullptr;
    DeclarationName Name =
      Context.DeclarationNames.getCXXOperatorName(OO_Delete);
    if (FindDeallocationFunction(MD->getLocation(), MD->getParent(), Name,
                                 OperatorDelete, /*Diagnose*/false)) {
      if (Diagnose)
        Diag(RD->getLocation(), diag::note_deleted_dtor_no_operator_delete);
      return true;
    }
  }

  SpecialMemberDeletionInfo SMI(*this, MD, CSM, ICI, Diagnose);

  // Per DR1611, do not consider virtual bases of constructors of abstract
  // classes, since we are not going to construct them.
  // Per DR1658, do not consider virtual bases of destructors of abstract
  // classes either.
  // Per DR2180, for assignment operators we only assign (and thus only
  // consider) direct bases.
  if (SMI.visit(SMI.IsAssignment ? SMI.VisitDirectBases
                                 : SMI.VisitPotentiallyConstructedBases))
    return true;

  if (SMI.shouldDeleteForAllConstMembers())
    return true;

  if (getLangOpts().CUDA) {
    // We should delete the special member in CUDA mode if target inference
    // failed.
    // For inherited constructors (non-null ICI), CSM may be passed so that MD
    // is treated as certain special member, which may not reflect what special
    // member MD really is. However inferCUDATargetForImplicitSpecialMember
    // expects CSM to match MD, therefore recalculate CSM.
    assert(ICI || CSM == getSpecialMember(MD));
    auto RealCSM = CSM;
    if (ICI)
      RealCSM = getSpecialMember(MD);

    return inferCUDATargetForImplicitSpecialMember(RD, RealCSM, MD,
                                                   SMI.ConstArg, Diagnose);
  }

  return false;
}

/// Perform lookup for a special member of the specified kind, and determine
/// whether it is trivial. If the triviality can be determined without the
/// lookup, skip it. This is intended for use when determining whether a
/// special member of a containing object is trivial, and thus does not ever
/// perform overload resolution for default constructors.
///
/// If \p Selected is not \c NULL, \c *Selected will be filled in with the
/// member that was most likely to be intended to be trivial, if any.
///
/// If \p ForCall is true, look at CXXRecord::HasTrivialSpecialMembersForCall to
/// determine whether the special member is trivial.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
                                     Sema::CXXSpecialMember CSM, unsigned Quals,
                                     bool ConstRHS,
                                     Sema::TrivialABIHandling TAH,
                                     CXXMethodDecl **Selected) {
  if (Selected)
    *Selected = nullptr;

  switch (CSM) {
  case Sema::CXXInvalid:
    llvm_unreachable("not a special member");

  case Sema::CXXDefaultConstructor:
    // C++11 [class.ctor]p5:
    //   A default constructor is trivial if:
    //    - all the [direct subobjects] have trivial default constructors
    //
    // Note, no overload resolution is performed in this case.
    if (RD->hasTrivialDefaultConstructor())
      return true;

    if (Selected) {
      // If there's a default constructor which could have been trivial, dig it
      // out. Otherwise, if there's any user-provided default constructor, point
      // to that as an example of why there's not a trivial one.
      CXXConstructorDecl *DefCtor = nullptr;
      if (RD->needsImplicitDefaultConstructor())
        S.DeclareImplicitDefaultConstructor(RD);
      for (auto *CI : RD->ctors()) {
        if (!CI->isDefaultConstructor())
          continue;
        DefCtor = CI;
        if (!DefCtor->isUserProvided())
          break;
      }

      *Selected = DefCtor;
    }

    return false;

  case Sema::CXXDestructor:
    // C++11 [class.dtor]p5:
    //   A destructor is trivial if:
    //    - all the direct [subobjects] have trivial destructors
    if (RD->hasTrivialDestructor() ||
        (TAH == Sema::TAH_ConsiderTrivialABI &&
         RD->hasTrivialDestructorForCall()))
      return true;

    if (Selected) {
      if (RD->needsImplicitDestructor())
        S.DeclareImplicitDestructor(RD);
      *Selected = RD->getDestructor();
    }

    return false;

  case Sema::CXXCopyConstructor:
    // C++11 [class.copy]p12:
    //   A copy constructor is trivial if:
    //    - the constructor selected to copy each direct [subobject] is trivial
    if (RD->hasTrivialCopyConstructor() ||
        (TAH == Sema::TAH_ConsiderTrivialABI &&
         RD->hasTrivialCopyConstructorForCall())) {
      if (Quals == Qualifiers::Const)
        // We must either select the trivial copy constructor or reach an
        // ambiguity; no need to actually perform overload resolution.
        return true;
    } else if (!Selected) {
      return false;
    }
    // In C++98, we are not supposed to perform overload resolution here, but we
    // treat that as a language defect, as suggested on cxx-abi-dev, to treat
    // cases like B as having a non-trivial copy constructor:
    //   struct A { template<typename T> A(T&); };
    //   struct B { mutable A a; };
    goto NeedOverloadResolution;

  case Sema::CXXCopyAssignment:
    // C++11 [class.copy]p25:
    //   A copy assignment operator is trivial if:
    //    - the assignment operator selected to copy each direct [subobject] is
    //      trivial
    if (RD->hasTrivialCopyAssignment()) {
      if (Quals == Qualifiers::Const)
        return true;
    } else if (!Selected) {
      return false;
    }
    // In C++98, we are not supposed to perform overload resolution here, but we
    // treat that as a language defect.
    goto NeedOverloadResolution;

  case Sema::CXXMoveConstructor:
  case Sema::CXXMoveAssignment:
  NeedOverloadResolution:
    Sema::SpecialMemberOverloadResult SMOR =
        lookupCallFromSpecialMember(S, RD, CSM, Quals, ConstRHS);

    // The standard doesn't describe how to behave if the lookup is ambiguous.
    // We treat it as not making the member non-trivial, just like the standard
    // mandates for the default constructor. This should rarely matter, because
    // the member will also be deleted.
    if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::Ambiguous)
      return true;

    if (!SMOR.getMethod()) {
      assert(SMOR.getKind() ==
             Sema::SpecialMemberOverloadResult::NoMemberOrDeleted);
      return false;
    }

    // We deliberately don't check if we found a deleted special member. We're
    // not supposed to!
    if (Selected)
      *Selected = SMOR.getMethod();

    if (TAH == Sema::TAH_ConsiderTrivialABI &&
        (CSM == Sema::CXXCopyConstructor || CSM == Sema::CXXMoveConstructor))
      return SMOR.getMethod()->isTrivialForCall();
    return SMOR.getMethod()->isTrivial();
  }

  llvm_unreachable("unknown special method kind");
}

static CXXConstructorDecl *findUserDeclaredCtor(CXXRecordDecl *RD) {
  for (auto *CI : RD->ctors())
    if (!CI->isImplicit())
      return CI;

  // Look for constructor templates.
  typedef CXXRecordDecl::specific_decl_iterator<FunctionTemplateDecl> tmpl_iter;
  for (tmpl_iter TI(RD->decls_begin()), TE(RD->decls_end()); TI != TE; ++TI) {
    if (CXXConstructorDecl *CD =
          dyn_cast<CXXConstructorDecl>(TI->getTemplatedDecl()))
      return CD;
  }

  return nullptr;
}

/// The kind of subobject we are checking for triviality. The values of this
/// enumeration are used in diagnostics.
enum TrivialSubobjectKind {
  /// The subobject is a base class.
  TSK_BaseClass,
  /// The subobject is a non-static data member.
  TSK_Field,
  /// The object is actually the complete object.
  TSK_CompleteObject
};

/// Check whether the special member selected for a given type would be trivial.
static bool checkTrivialSubobjectCall(Sema &S, SourceLocation SubobjLoc,
                                      QualType SubType, bool ConstRHS,
                                      Sema::CXXSpecialMember CSM,
                                      TrivialSubobjectKind Kind,
                                      Sema::TrivialABIHandling TAH, bool Diagnose) {
  CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl();
  if (!SubRD)
    return true;

  CXXMethodDecl *Selected;
  if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
                               ConstRHS, TAH, Diagnose ? &Selected : nullptr))
    return true;

  if (Diagnose) {
    if (ConstRHS)
      SubType.addConst();

    if (!Selected && CSM == Sema::CXXDefaultConstructor) {
      S.Diag(SubobjLoc, diag::note_nontrivial_no_def_ctor)
        << Kind << SubType.getUnqualifiedType();
      if (CXXConstructorDecl *CD = findUserDeclaredCtor(SubRD))
        S.Diag(CD->getLocation(), diag::note_user_declared_ctor);
    } else if (!Selected)
      S.Diag(SubobjLoc, diag::note_nontrivial_no_copy)
        << Kind << SubType.getUnqualifiedType() << CSM << SubType;
    else if (Selected->isUserProvided()) {
      if (Kind == TSK_CompleteObject)
        S.Diag(Selected->getLocation(), diag::note_nontrivial_user_provided)
          << Kind << SubType.getUnqualifiedType() << CSM;
      else {
        S.Diag(SubobjLoc, diag::note_nontrivial_user_provided)
          << Kind << SubType.getUnqualifiedType() << CSM;
        S.Diag(Selected->getLocation(), diag::note_declared_at);
      }
    } else {
      if (Kind != TSK_CompleteObject)
        S.Diag(SubobjLoc, diag::note_nontrivial_subobject)
          << Kind << SubType.getUnqualifiedType() << CSM;

      // Explain why the defaulted or deleted special member isn't trivial.
      S.SpecialMemberIsTrivial(Selected, CSM, Sema::TAH_IgnoreTrivialABI,
                               Diagnose);
    }
  }

  return false;
}

/// Check whether the members of a class type allow a special member to be
/// trivial.
static bool checkTrivialClassMembers(Sema &S, CXXRecordDecl *RD,
                                     Sema::CXXSpecialMember CSM,
                                     bool ConstArg,
                                     Sema::TrivialABIHandling TAH,
                                     bool Diagnose) {
  for (const auto *FI : RD->fields()) {
    if (FI->isInvalidDecl() || FI->isUnnamedBitfield())
      continue;

    QualType FieldType = S.Context.getBaseElementType(FI->getType());

    // Pretend anonymous struct or union members are members of this class.
    if (FI->isAnonymousStructOrUnion()) {
      if (!checkTrivialClassMembers(S, FieldType->getAsCXXRecordDecl(),
                                    CSM, ConstArg, TAH, Diagnose))
        return false;
      continue;
    }

    // C++11 [class.ctor]p5:
    //   A default constructor is trivial if [...]
    //    -- no non-static data member of its class has a
    //       brace-or-equal-initializer
    if (CSM == Sema::CXXDefaultConstructor && FI->hasInClassInitializer()) {
      if (Diagnose)
        S.Diag(FI->getLocation(), diag::note_nontrivial_in_class_init) << FI;
      return false;
    }

    // Objective C ARC 4.3.5:
    //   [...] nontrivally ownership-qualified types are [...] not trivially
    //   default constructible, copy constructible, move constructible, copy
    //   assignable, move assignable, or destructible [...]
    if (FieldType.hasNonTrivialObjCLifetime()) {
      if (Diagnose)
        S.Diag(FI->getLocation(), diag::note_nontrivial_objc_ownership)
          << RD << FieldType.getObjCLifetime();
      return false;
    }

    bool ConstRHS = ConstArg && !FI->isMutable();
    if (!checkTrivialSubobjectCall(S, FI->getLocation(), FieldType, ConstRHS,
                                   CSM, TSK_Field, TAH, Diagnose))
      return false;
  }

  return true;
}

/// Diagnose why the specified class does not have a trivial special member of
/// the given kind.
void Sema::DiagnoseNontrivial(const CXXRecordDecl *RD, CXXSpecialMember CSM) {
  QualType Ty = Context.getRecordType(RD);

  bool ConstArg = (CSM == CXXCopyConstructor || CSM == CXXCopyAssignment);
  checkTrivialSubobjectCall(*this, RD->getLocation(), Ty, ConstArg, CSM,
                            TSK_CompleteObject, TAH_IgnoreTrivialABI,
                            /*Diagnose*/true);
}

/// Determine whether a defaulted or deleted special member function is trivial,
/// as specified in C++11 [class.ctor]p5, C++11 [class.copy]p12,
/// C++11 [class.copy]p25, and C++11 [class.dtor]p5.
bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM,
                                  TrivialABIHandling TAH, bool Diagnose) {
  assert(!MD->isUserProvided() && CSM != CXXInvalid && "not special enough");

  CXXRecordDecl *RD = MD->getParent();

  bool ConstArg = false;

  // C++11 [class.copy]p12, p25: [DR1593]
  //   A [special member] is trivial if [...] its parameter-type-list is
  //   equivalent to the parameter-type-list of an implicit declaration [...]
  switch (CSM) {
  case CXXDefaultConstructor:
  case CXXDestructor:
    // Trivial default constructors and destructors cannot have parameters.
    break;

  case CXXCopyConstructor:
  case CXXCopyAssignment: {
    // Trivial copy operations always have const, non-volatile parameter types.
    ConstArg = true;
    const ParmVarDecl *Param0 = MD->getParamDecl(0);
    const ReferenceType *RT = Param0->getType()->getAs<ReferenceType>();
    if (!RT || RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) {
      if (Diagnose)
        Diag(Param0->getLocation(), diag::note_nontrivial_param_type)
          << Param0->getSourceRange() << Param0->getType()
          << Context.getLValueReferenceType(
               Context.getRecordType(RD).withConst());
      return false;
    }
    break;
  }

  case CXXMoveConstructor:
  case CXXMoveAssignment: {
    // Trivial move operations always have non-cv-qualified parameters.
    const ParmVarDecl *Param0 = MD->getParamDecl(0);
    const RValueReferenceType *RT =
      Param0->getType()->getAs<RValueReferenceType>();
    if (!RT || RT->getPointeeType().getCVRQualifiers()) {
      if (Diagnose)
        Diag(Param0->getLocation(), diag::note_nontrivial_param_type)
          << Param0->getSourceRange() << Param0->getType()
          << Context.getRValueReferenceType(Context.getRecordType(RD));
      return false;
    }
    break;
  }

  case CXXInvalid:
    llvm_unreachable("not a special member");
  }

  if (MD->getMinRequiredArguments() < MD->getNumParams()) {
    if (Diagnose)
      Diag(MD->getParamDecl(MD->getMinRequiredArguments())->getLocation(),
           diag::note_nontrivial_default_arg)
        << MD->getParamDecl(MD->getMinRequiredArguments())->getSourceRange();
    return false;
  }
  if (MD->isVariadic()) {
    if (Diagnose)
      Diag(MD->getLocation(), diag::note_nontrivial_variadic);
    return false;
  }

  // C++11 [class.ctor]p5, C++11 [class.dtor]p5:
  //   A copy/move [constructor or assignment operator] is trivial if
  //    -- the [member] selected to copy/move each direct base class subobject
  //       is trivial
  //
  // C++11 [class.copy]p12, C++11 [class.copy]p25:
  //   A [default constructor or destructor] is trivial if
  //    -- all the direct base classes have trivial [default constructors or
  //       destructors]
  for (const auto &BI : RD->bases())
    if (!checkTrivialSubobjectCall(*this, BI.getBeginLoc(), BI.getType(),
                                   ConstArg, CSM, TSK_BaseClass, TAH, Diagnose))
      return false;

  // C++11 [class.ctor]p5, C++11 [class.dtor]p5:
  //   A copy/move [constructor or assignment operator] for a class X is
  //   trivial if
  //    -- for each non-static data member of X that is of class type (or array
  //       thereof), the constructor selected to copy/move that member is
  //       trivial
  //
  // C++11 [class.copy]p12, C++11 [class.copy]p25:
  //   A [default constructor or destructor] is trivial if
  //    -- for all of the non-static data members of its class that are of class
  //       type (or array thereof), each such class has a trivial [default
  //       constructor or destructor]
  if (!checkTrivialClassMembers(*this, RD, CSM, ConstArg, TAH, Diagnose))
    return false;

  // C++11 [class.dtor]p5:
  //   A destructor is trivial if [...]
  //    -- the destructor is not virtual
  if (CSM == CXXDestructor && MD->isVirtual()) {
    if (Diagnose)
      Diag(MD->getLocation(), diag::note_nontrivial_virtual_dtor) << RD;
    return false;
  }

  // C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25:
  //   A [special member] for class X is trivial if [...]
  //    -- class X has no virtual functions and no virtual base classes
  if (CSM != CXXDestructor && MD->getParent()->isDynamicClass()) {
    if (!Diagnose)
      return false;

    if (RD->getNumVBases()) {
      // Check for virtual bases. We already know that the corresponding
      // member in all bases is trivial, so vbases must all be direct.
      CXXBaseSpecifier &BS = *RD->vbases_begin();
      assert(BS.isVirtual());
      Diag(BS.getBeginLoc(), diag::note_nontrivial_has_virtual) << RD << 1;
      return false;
    }

    // Must have a virtual method.
    for (const auto *MI : RD->methods()) {
      if (MI->isVirtual()) {
        SourceLocation MLoc = MI->getBeginLoc();
        Diag(MLoc, diag::note_nontrivial_has_virtual) << RD << 0;
        return false;
      }
    }

    llvm_unreachable("dynamic class with no vbases and no virtual functions");
  }

  // Looks like it's trivial!
  return true;
}

namespace {
struct FindHiddenVirtualMethod {
  Sema *S;
  CXXMethodDecl *Method;
  llvm::SmallPtrSet<const CXXMethodDecl *, 8> OverridenAndUsingBaseMethods;
  SmallVector<CXXMethodDecl *, 8> OverloadedMethods;

private:
  /// Check whether any most overridden method from MD in Methods
  static bool CheckMostOverridenMethods(
      const CXXMethodDecl *MD,
      const llvm::SmallPtrSetImpl<const CXXMethodDecl *> &Methods) {
    if (MD->size_overridden_methods() == 0)
      return Methods.count(MD->getCanonicalDecl());
    for (const CXXMethodDecl *O : MD->overridden_methods())
      if (CheckMostOverridenMethods(O, Methods))
        return true;
    return false;
  }

public:
  /// Member lookup function that determines whether a given C++
  /// method overloads virtual methods in a base class without overriding any,
  /// to be used with CXXRecordDecl::lookupInBases().
  bool operator()(const CXXBaseSpecifier *Specifier, CXXBasePath &Path) {
    RecordDecl *BaseRecord =
        Specifier->getType()->getAs<RecordType>()->getDecl();

    DeclarationName Name = Method->getDeclName();
    assert(Name.getNameKind() == DeclarationName::Identifier);

    bool foundSameNameMethod = false;
    SmallVector<CXXMethodDecl *, 8> overloadedMethods;
    for (Path.Decls = BaseRecord->lookup(Name); !Path.Decls.empty();
         Path.Decls = Path.Decls.slice(1)) {
      NamedDecl *D = Path.Decls.front();
      if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
        MD = MD->getCanonicalDecl();
        foundSameNameMethod = true;
        // Interested only in hidden virtual methods.
        if (!MD->isVirtual())
          continue;
        // If the method we are checking overrides a method from its base
        // don't warn about the other overloaded methods. Clang deviates from
        // GCC by only diagnosing overloads of inherited virtual functions that
        // do not override any other virtual functions in the base. GCC's
        // -Woverloaded-virtual diagnoses any derived function hiding a virtual
        // function from a base class. These cases may be better served by a
        // warning (not specific to virtual functions) on call sites when the
        // call would select a different function from the base class, were it
        // visible.
        // See FIXME in test/SemaCXX/warn-overload-virtual.cpp for an example.
        if (!S->IsOverload(Method, MD, false))
          return true;
        // Collect the overload only if its hidden.
        if (!CheckMostOverridenMethods(MD, OverridenAndUsingBaseMethods))
          overloadedMethods.push_back(MD);
      }
    }

    if (foundSameNameMethod)
      OverloadedMethods.append(overloadedMethods.begin(),
                               overloadedMethods.end());
    return foundSameNameMethod;
  }
};
} // end anonymous namespace

/// Add the most overriden methods from MD to Methods
static void AddMostOverridenMethods(const CXXMethodDecl *MD,
                        llvm::SmallPtrSetImpl<const CXXMethodDecl *>& Methods) {
  if (MD->size_overridden_methods() == 0)
    Methods.insert(MD->getCanonicalDecl());
  else
    for (const CXXMethodDecl *O : MD->overridden_methods())
      AddMostOverridenMethods(O, Methods);
}

/// Check if a method overloads virtual methods in a base class without
/// overriding any.
void Sema::FindHiddenVirtualMethods(CXXMethodDecl *MD,
                          SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
  if (!MD->getDeclName().isIdentifier())
    return;

  CXXBasePaths Paths(/*FindAmbiguities=*/true, // true to look in all bases.
                     /*bool RecordPaths=*/false,
                     /*bool DetectVirtual=*/false);
  FindHiddenVirtualMethod FHVM;
  FHVM.Method = MD;
  FHVM.S = this;

  // Keep the base methods that were overridden or introduced in the subclass
  // by 'using' in a set. A base method not in this set is hidden.
  CXXRecordDecl *DC = MD->getParent();
  DeclContext::lookup_result R = DC->lookup(MD->getDeclName());
  for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) {
    NamedDecl *ND = *I;
    if (UsingShadowDecl *shad = dyn_cast<UsingShadowDecl>(*I))
      ND = shad->getTargetDecl();
    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(ND))
      AddMostOverridenMethods(MD, FHVM.OverridenAndUsingBaseMethods);
  }

  if (DC->lookupInBases(FHVM, Paths))
    OverloadedMethods = FHVM.OverloadedMethods;
}

void Sema::NoteHiddenVirtualMethods(CXXMethodDecl *MD,
                          SmallVectorImpl<CXXMethodDecl*> &OverloadedMethods) {
  for (unsigned i = 0, e = OverloadedMethods.size(); i != e; ++i) {
    CXXMethodDecl *overloadedMD = OverloadedMethods[i];
    PartialDiagnostic PD = PDiag(
         diag::note_hidden_overloaded_virtual_declared_here) << overloadedMD;
    HandleFunctionTypeMismatch(PD, MD->getType(), overloadedMD->getType());
    Diag(overloadedMD->getLocation(), PD);
  }
}

/// Diagnose methods which overload virtual methods in a base class
/// without overriding any.
void Sema::DiagnoseHiddenVirtualMethods(CXXMethodDecl *MD) {
  if (MD->isInvalidDecl())
    return;

  if (Diags.isIgnored(diag::warn_overloaded_virtual, MD->getLocation()))
    return;

  SmallVector<CXXMethodDecl *, 8> OverloadedMethods;
  FindHiddenVirtualMethods(MD, OverloadedMethods);
  if (!OverloadedMethods.empty()) {
    Diag(MD->getLocation(), diag::warn_overloaded_virtual)
      << MD << (OverloadedMethods.size() > 1);

    NoteHiddenVirtualMethods(MD, OverloadedMethods);
  }
}

void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
  auto PrintDiagAndRemoveAttr = [&]() {
    // No diagnostics if this is a template instantiation.
    if (!isTemplateInstantiation(RD.getTemplateSpecializationKind()))
      Diag(RD.getAttr<TrivialABIAttr>()->getLocation(),
           diag::ext_cannot_use_trivial_abi) << &RD;
    RD.dropAttr<TrivialABIAttr>();
  };

  // Ill-formed if the struct has virtual functions.
  if (RD.isPolymorphic()) {
    PrintDiagAndRemoveAttr();
    return;
  }

  for (const auto &B : RD.bases()) {
    // Ill-formed if the base class is non-trivial for the purpose of calls or a
    // virtual base.
    if ((!B.getType()->isDependentType() &&
         !B.getType()->getAsCXXRecordDecl()->canPassInRegisters()) ||
        B.isVirtual()) {
      PrintDiagAndRemoveAttr();
      return;
    }
  }

  for (const auto *FD : RD.fields()) {
    // Ill-formed if the field is an ObjectiveC pointer or of a type that is
    // non-trivial for the purpose of calls.
    QualType FT = FD->getType();
    if (FT.getObjCLifetime() == Qualifiers::OCL_Weak) {
      PrintDiagAndRemoveAttr();
      return;
    }

    if (const auto *RT = FT->getBaseElementTypeUnsafe()->getAs<RecordType>())
      if (!RT->isDependentType() &&
          !cast<CXXRecordDecl>(RT->getDecl())->canPassInRegisters()) {
        PrintDiagAndRemoveAttr();
        return;
      }
  }
}

void Sema::ActOnFinishCXXMemberSpecification(
    Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac,
    SourceLocation RBrac, const ParsedAttributesView &AttrList) {
  if (!TagDecl)
    return;

  AdjustDeclIfTemplate(TagDecl);

  for (const ParsedAttr &AL : AttrList) {
    if (AL.getKind() != ParsedAttr::AT_Visibility)
      continue;
    AL.setInvalid();
    Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored)
        << AL.getName();
  }

  ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
              // strict aliasing violation!
              reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
              FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);

  CheckCompletedCXXClass(cast<CXXRecordDecl>(TagDecl));
}

/// AddImplicitlyDeclaredMembersToClass - Adds any implicitly-declared
/// special functions, such as the default constructor, copy
/// constructor, or destructor, to the given C++ class (C++
/// [special]p1).  This routine can only be executed just before the
/// definition of the class is complete.
void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) {
  if (ClassDecl->needsImplicitDefaultConstructor()) {
    ++getASTContext().NumImplicitDefaultConstructors;

    if (ClassDecl->hasInheritedConstructor())
      DeclareImplicitDefaultConstructor(ClassDecl);
  }

  if (ClassDecl->needsImplicitCopyConstructor()) {
    ++getASTContext().NumImplicitCopyConstructors;

    // If the properties or semantics of the copy constructor couldn't be
    // determined while the class was being declared, force a declaration
    // of it now.
    if (ClassDecl->needsOverloadResolutionForCopyConstructor() ||
        ClassDecl->hasInheritedConstructor())
      DeclareImplicitCopyConstructor(ClassDecl);
    // For the MS ABI we need to know whether the copy ctor is deleted. A
    // prerequisite for deleting the implicit copy ctor is that the class has a
    // move ctor or move assignment that is either user-declared or whose
    // semantics are inherited from a subobject. FIXME: We should provide a more
    // direct way for CodeGen to ask whether the constructor was deleted.
    else if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
             (ClassDecl->hasUserDeclaredMoveConstructor() ||
              ClassDecl->needsOverloadResolutionForMoveConstructor() ||
              ClassDecl->hasUserDeclaredMoveAssignment() ||
              ClassDecl->needsOverloadResolutionForMoveAssignment()))
      DeclareImplicitCopyConstructor(ClassDecl);
  }

  if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) {
    ++getASTContext().NumImplicitMoveConstructors;

    if (ClassDecl->needsOverloadResolutionForMoveConstructor() ||
        ClassDecl->hasInheritedConstructor())
      DeclareImplicitMoveConstructor(ClassDecl);
  }

  if (ClassDecl->needsImplicitCopyAssignment()) {
    ++getASTContext().NumImplicitCopyAssignmentOperators;

    // If we have a dynamic class, then the copy assignment operator may be
    // virtual, so we have to declare it immediately. This ensures that, e.g.,
    // it shows up in the right place in the vtable and that we diagnose
    // problems with the implicit exception specification.
    if (ClassDecl->isDynamicClass() ||
        ClassDecl->needsOverloadResolutionForCopyAssignment() ||
        ClassDecl->hasInheritedAssignment())
      DeclareImplicitCopyAssignment(ClassDecl);
  }

  if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveAssignment()) {
    ++getASTContext().NumImplicitMoveAssignmentOperators;

    // Likewise for the move assignment operator.
    if (ClassDecl->isDynamicClass() ||
        ClassDecl->needsOverloadResolutionForMoveAssignment() ||
        ClassDecl->hasInheritedAssignment())
      DeclareImplicitMoveAssignment(ClassDecl);
  }

  if (ClassDecl->needsImplicitDestructor()) {
    ++getASTContext().NumImplicitDestructors;

    // If we have a dynamic class, then the destructor may be virtual, so we
    // have to declare the destructor immediately. This ensures that, e.g., it
    // shows up in the right place in the vtable and that we diagnose problems
    // with the implicit exception specification.
    if (ClassDecl->isDynamicClass() ||
        ClassDecl->needsOverloadResolutionForDestructor())
      DeclareImplicitDestructor(ClassDecl);
  }
}

unsigned Sema::ActOnReenterTemplateScope(Scope *S, Decl *D) {
  if (!D)
    return 0;

  // The order of template parameters is not important here. All names
  // get added to the same scope.
  SmallVector<TemplateParameterList *, 4> ParameterLists;

  if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
    D = TD->getTemplatedDecl();

  if (auto *PSD = dyn_cast<ClassTemplatePartialSpecializationDecl>(D))
    ParameterLists.push_back(PSD->getTemplateParameters());

  if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
    for (unsigned i = 0; i < DD->getNumTemplateParameterLists(); ++i)
      ParameterLists.push_back(DD->getTemplateParameterList(i));

    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
      if (FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
        ParameterLists.push_back(FTD->getTemplateParameters());
    }
  }

  if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
    for (unsigned i = 0; i < TD->getNumTemplateParameterLists(); ++i)
      ParameterLists.push_back(TD->getTemplateParameterList(i));

    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(TD)) {
      if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
        ParameterLists.push_back(CTD->getTemplateParameters());
    }
  }

  unsigned Count = 0;
  for (TemplateParameterList *Params : ParameterLists) {
    if (Params->size() > 0)
      // Ignore explicit specializations; they don't contribute to the template
      // depth.
      ++Count;
    for (NamedDecl *Param : *Params) {
      if (Param->getDeclName()) {
        S->AddDecl(Param);
        IdResolver.AddDecl(Param);
      }
    }
  }

  return Count;
}

void Sema::ActOnStartDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
  if (!RecordD) return;
  AdjustDeclIfTemplate(RecordD);
  CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordD);
  PushDeclContext(S, Record);
}

void Sema::ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *RecordD) {
  if (!RecordD) return;
  PopDeclContext();
}

/// This is used to implement the constant expression evaluation part of the
/// attribute enable_if extension. There is nothing in standard C++ which would
/// require reentering parameters.
void Sema::ActOnReenterCXXMethodParameter(Scope *S, ParmVarDecl *Param) {
  if (!Param)
    return;

  S->AddDecl(Param);
  if (Param->getDeclName())
    IdResolver.AddDecl(Param);
}

/// ActOnStartDelayedCXXMethodDeclaration - We have completed
/// parsing a top-level (non-nested) C++ class, and we are now
/// parsing those parts of the given Method declaration that could
/// not be parsed earlier (C++ [class.mem]p2), such as default
/// arguments. This action should enter the scope of the given
/// Method declaration as if we had just parsed the qualified method
/// name. However, it should not bring the parameters into scope;
/// that will be performed by ActOnDelayedCXXMethodParameter.
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
}

/// ActOnDelayedCXXMethodParameter - We've already started a delayed
/// C++ method declaration. We're (re-)introducing the given
/// function parameter into scope for use in parsing later parts of
/// the method declaration. For example, we could see an
/// ActOnParamDefaultArgument event for this parameter.
void Sema::ActOnDelayedCXXMethodParameter(Scope *S, Decl *ParamD) {
  if (!ParamD)
    return;

  ParmVarDecl *Param = cast<ParmVarDecl>(ParamD);

  // If this parameter has an unparsed default argument, clear it out
  // to make way for the parsed default argument.
  if (Param->hasUnparsedDefaultArg())
    Param->setDefaultArg(nullptr);

  S->AddDecl(Param);
  if (Param->getDeclName())
    IdResolver.AddDecl(Param);
}

/// ActOnFinishDelayedCXXMethodDeclaration - We have finished
/// processing the delayed method declaration for Method. The method
/// declaration is now considered finished. There may be a separate
/// ActOnStartOfFunctionDef action later (not necessarily
/// immediately!) for this method, if it was also defined inside the
/// class body.
void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
  if (!MethodD)
    return;

  AdjustDeclIfTemplate(MethodD);

  FunctionDecl *Method = cast<FunctionDecl>(MethodD);

  // Now that we have our default arguments, check the constructor
  // again. It could produce additional diagnostics or affect whether
  // the class has implicitly-declared destructors, among other
  // things.
  if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(Method))
    CheckConstructor(Constructor);

  // Check the default arguments, which we may have added.
  if (!Method->isInvalidDecl())
    CheckCXXDefaultArguments(Method);
}

/// CheckConstructorDeclarator - Called by ActOnDeclarator to check
/// the well-formedness of the constructor declarator @p D with type @p
/// R. If there are any errors in the declarator, this routine will
/// emit diagnostics and set the invalid bit to true.  In any case, the type
/// will be updated to reflect a well-formed type for the constructor and
/// returned.
QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
                                          StorageClass &SC) {
  bool isVirtual = D.getDeclSpec().isVirtualSpecified();

  // C++ [class.ctor]p3:
  //   A constructor shall not be virtual (10.3) or static (9.4). A
  //   constructor can be invoked for a const, volatile or const
  //   volatile object. A constructor shall not be declared const,
  //   volatile, or const volatile (9.3.2).
  if (isVirtual) {
    if (!D.isInvalidType())
      Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
        << "virtual" << SourceRange(D.getDeclSpec().getVirtualSpecLoc())
        << SourceRange(D.getIdentifierLoc());
    D.setInvalidType();
  }
  if (SC == SC_Static) {
    if (!D.isInvalidType())
      Diag(D.getIdentifierLoc(), diag::err_constructor_cannot_be)
        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
        << SourceRange(D.getIdentifierLoc());
    D.setInvalidType();
    SC = SC_None;
  }

  if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) {
    diagnoseIgnoredQualifiers(
        diag::err_constructor_return_type, TypeQuals, SourceLocation(),
        D.getDeclSpec().getConstSpecLoc(), D.getDeclSpec().getVolatileSpecLoc(),
        D.getDeclSpec().getRestrictSpecLoc(),
        D.getDeclSpec().getAtomicSpecLoc());
    D.setInvalidType();
  }

  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
  if (FTI.hasMethodTypeQualifiers()) {
    FTI.MethodQualifiers->forEachQualifier(
        [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
          Diag(SL, diag::err_invalid_qualified_constructor)
              << QualName << SourceRange(SL);
        });
    D.setInvalidType();
  }

  // C++0x [class.ctor]p4:
  //   A constructor shall not be declared with a ref-qualifier.
  if (FTI.hasRefQualifier()) {
    Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor)
      << FTI.RefQualifierIsLValueRef
      << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
    D.setInvalidType();
  }

  // Rebuild the function type "R" without any type qualifiers (in
  // case any of the errors above fired) and with "void" as the
  // return type, since constructors don't have return types.
  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
  if (Proto->getReturnType() == Context.VoidTy && !D.isInvalidType())
    return R;

  FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
  EPI.TypeQuals = Qualifiers();
  EPI.RefQualifier = RQ_None;

  return Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
}

/// CheckConstructor - Checks a fully-formed constructor for
/// well-formedness, issuing any diagnostics required. Returns true if
/// the constructor declarator is invalid.
void Sema::CheckConstructor(CXXConstructorDecl *Constructor) {
  CXXRecordDecl *ClassDecl
    = dyn_cast<CXXRecordDecl>(Constructor->getDeclContext());
  if (!ClassDecl)
    return Constructor->setInvalidDecl();

  // C++ [class.copy]p3:
  //   A declaration of a constructor for a class X is ill-formed if
  //   its first parameter is of type (optionally cv-qualified) X and
  //   either there are no other parameters or else all other
  //   parameters have default arguments.
  if (!Constructor->isInvalidDecl() &&
      ((Constructor->getNumParams() == 1) ||
       (Constructor->getNumParams() > 1 &&
        Constructor->getParamDecl(1)->hasDefaultArg())) &&
      Constructor->getTemplateSpecializationKind()
                                              != TSK_ImplicitInstantiation) {
    QualType ParamType = Constructor->getParamDecl(0)->getType();
    QualType ClassTy = Context.getTagDeclType(ClassDecl);
    if (Context.getCanonicalType(ParamType).getUnqualifiedType() == ClassTy) {
      SourceLocation ParamLoc = Constructor->getParamDecl(0)->getLocation();
      const char *ConstRef
        = Constructor->getParamDecl(0)->getIdentifier() ? "const &"
                                                        : " const &";
      Diag(ParamLoc, diag::err_constructor_byvalue_arg)
        << FixItHint::CreateInsertion(ParamLoc, ConstRef);

      // FIXME: Rather that making the constructor invalid, we should endeavor
      // to fix the type.
      Constructor->setInvalidDecl();
    }
  }
}

/// CheckDestructor - Checks a fully-formed destructor definition for
/// well-formedness, issuing any diagnostics required.  Returns true
/// on error.
bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
  CXXRecordDecl *RD = Destructor->getParent();

  if (!Destructor->getOperatorDelete() && Destructor->isVirtual()) {
    SourceLocation Loc;

    if (!Destructor->isImplicit())
      Loc = Destructor->getLocation();
    else
      Loc = RD->getLocation();

    // If we have a virtual destructor, look up the deallocation function
    if (FunctionDecl *OperatorDelete =
            FindDeallocationFunctionForDestructor(Loc, RD)) {
      Expr *ThisArg = nullptr;

      // If the notional 'delete this' expression requires a non-trivial
      // conversion from 'this' to the type of a destroying operator delete's
      // first parameter, perform that conversion now.
      if (OperatorDelete->isDestroyingOperatorDelete()) {
        QualType ParamType = OperatorDelete->getParamDecl(0)->getType();
        if (!declaresSameEntity(ParamType->getAsCXXRecordDecl(), RD)) {
          // C++ [class.dtor]p13:
          //   ... as if for the expression 'delete this' appearing in a
          //   non-virtual destructor of the destructor's class.
          ContextRAII SwitchContext(*this, Destructor);
          ExprResult This =
              ActOnCXXThis(OperatorDelete->getParamDecl(0)->getLocation());
          assert(!This.isInvalid() && "couldn't form 'this' expr in dtor?");
          This = PerformImplicitConversion(This.get(), ParamType, AA_Passing);
          if (This.isInvalid()) {
            // FIXME: Register this as a context note so that it comes out
            // in the right order.
            Diag(Loc, diag::note_implicit_delete_this_in_destructor_here);
            return true;
          }
          ThisArg = This.get();
        }
      }

      DiagnoseUseOfDecl(OperatorDelete, Loc);
      MarkFunctionReferenced(Loc, OperatorDelete);
      Destructor->setOperatorDelete(OperatorDelete, ThisArg);
    }
  }

  return false;
}

/// CheckDestructorDeclarator - Called by ActOnDeclarator to check
/// the well-formednes of the destructor declarator @p D with type @p
/// R. If there are any errors in the declarator, this routine will
/// emit diagnostics and set the declarator to invalid.  Even if this happens,
/// will be updated to reflect a well-formed type for the destructor and
/// returned.
QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
                                         StorageClass& SC) {
  // C++ [class.dtor]p1:
  //   [...] A typedef-name that names a class is a class-name
  //   (7.1.3); however, a typedef-name that names a class shall not
  //   be used as the identifier in the declarator for a destructor
  //   declaration.
  QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName);
  if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>())
    Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
      << DeclaratorType << isa<TypeAliasDecl>(TT->getDecl());
  else if (const TemplateSpecializationType *TST =
             DeclaratorType->getAs<TemplateSpecializationType>())
    if (TST->isTypeAlias())
      Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
        << DeclaratorType << 1;

  // C++ [class.dtor]p2:
  //   A destructor is used to destroy objects of its class type. A
  //   destructor takes no parameters, and no return type can be
  //   specified for it (not even void). The address of a destructor
  //   shall not be taken. A destructor shall not be static. A
  //   destructor can be invoked for a const, volatile or const
  //   volatile object. A destructor shall not be declared const,
  //   volatile or const volatile (9.3.2).
  if (SC == SC_Static) {
    if (!D.isInvalidType())
      Diag(D.getIdentifierLoc(), diag::err_destructor_cannot_be)
        << "static" << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
        << SourceRange(D.getIdentifierLoc())
        << FixItHint::CreateRemoval(D.getDeclSpec().getStorageClassSpecLoc());

    SC = SC_None;
  }
  if (!D.isInvalidType()) {
    // Destructors don't have return types, but the parser will
    // happily parse something like:
    //
    //   class X {
    //     float ~X();
    //   };
    //
    // The return type will be eliminated later.
    if (D.getDeclSpec().hasTypeSpecifier())
      Diag(D.getIdentifierLoc(), diag::err_destructor_return_type)
        << SourceRange(D.getDeclSpec().getTypeSpecTypeLoc())
        << SourceRange(D.getIdentifierLoc());
    else if (unsigned TypeQuals = D.getDeclSpec().getTypeQualifiers()) {
      diagnoseIgnoredQualifiers(diag::err_destructor_return_type, TypeQuals,
                                SourceLocation(),
                                D.getDeclSpec().getConstSpecLoc(),
                                D.getDeclSpec().getVolatileSpecLoc(),
                                D.getDeclSpec().getRestrictSpecLoc(),
                                D.getDeclSpec().getAtomicSpecLoc());
      D.setInvalidType();
    }
  }

  DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
  if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) {
    FTI.MethodQualifiers->forEachQualifier(
        [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
          Diag(SL, diag::err_invalid_qualified_destructor)
              << QualName << SourceRange(SL);
        });
    D.setInvalidType();
  }

  // C++0x [class.dtor]p2:
  //   A destructor shall not be declared with a ref-qualifier.
  if (FTI.hasRefQualifier()) {
    Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor)
      << FTI.RefQualifierIsLValueRef
      << FixItHint::CreateRemoval(FTI.getRefQualifierLoc());
    D.setInvalidType();
  }

  // Make sure we don't have any parameters.
  if (FTIHasNonVoidParameters(FTI)) {
    Diag(D.getIdentifierLoc(), diag::err_destructor_with_params);

    // Delete the parameters.
    FTI.freeParams();
    D.setInvalidType();
  }

  // Make sure the destructor isn't variadic.
  if (FTI.isVariadic) {
    Diag(D.getIdentifierLoc(), diag::err_destructor_variadic);
    D.setInvalidType();
  }

  // Rebuild the function type "R" without any type qualifiers or
  // parameters (in case any of the errors above fired) and with
  // "void" as the return type, since destructors don't have return
  // types.
  if (!D.isInvalidType())
    return R;

  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();
  FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo();
  EPI.Variadic = false;
  EPI.TypeQuals = Qualifiers();
  EPI.RefQualifier = RQ_None;
  return Context.getFunctionType(Context.VoidTy, None, EPI);
}

static void extendLeft(SourceRange &R, SourceRange Before) {
  if (Before.isInvalid())
    return;
  R.setBegin(Before.getBegin());
  if (R.getEnd().isInvalid())
    R.setEnd(Before.getEnd());
}

static void extendRight(SourceRange &R, SourceRange After) {
  if (After.isInvalid())
    return;
  if (R.getBegin().isInvalid())
    R.setBegin(After.getBegin());
  R.setEnd(After.getEnd());
}

/// CheckConversionDeclarator - Called by ActOnDeclarator to check the
/// well-formednes of the conversion function declarator @p D with
/// type @p R. If there are any errors in the declarator, this routine
/// will emit diagnostics and return true. Otherwise, it will return
/// false. Either way, the type @p R will be updated to reflect a
/// well-formed type for the conversion operator.
void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
                                     StorageClass& SC) {
  // C++ [class.conv.fct]p1:
  //   Neither parameter types nor return type can be specified. The
  //   type of a conversion function (8.3.5) is "function taking no
  //   parameter returning conversion-type-id."
  if (SC == SC_Static) {
    if (!D.isInvalidType())
      Diag(D.getIdentifierLoc(), diag::err_conv_function_not_member)
        << SourceRange(D.getDeclSpec().getStorageClassSpecLoc())
        << D.getName().getSourceRange();
    D.setInvalidType();
    SC = SC_None;
  }

  TypeSourceInfo *ConvTSI = nullptr;
  QualType ConvType =
      GetTypeFromParser(D.getName().ConversionFunctionId, &ConvTSI);

  const DeclSpec &DS = D.getDeclSpec();
  if (DS.hasTypeSpecifier() && !D.isInvalidType()) {
    // Conversion functions don't have return types, but the parser will
    // happily parse something like:
    //
    //   class X {
    //     float operator bool();
    //   };
    //
    // The return type will be changed later anyway.
    Diag(D.getIdentifierLoc(), diag::err_conv_function_return_type)
      << SourceRange(DS.getTypeSpecTypeLoc())
      << SourceRange(D.getIdentifierLoc());
    D.setInvalidType();
  } else if (DS.getTypeQualifiers() && !D.isInvalidType()) {
    // It's also plausible that the user writes type qualifiers in the wrong
    // place, such as:
    //   struct S { const operator int(); };
    // FIXME: we could provide a fixit to move the qualifiers onto the
    // conversion type.
    Diag(D.getIdentifierLoc(), diag::err_conv_function_with_complex_decl)
        << SourceRange(D.getIdentifierLoc()) << 0;
    D.setInvalidType();
  }

  const FunctionProtoType *Proto = R->getAs<FunctionProtoType>();

  // Make sure we don't have any parameters.
  if (Proto->getNumParams() > 0) {
    Diag(D.getIdentifierLoc(), diag::err_conv_function_with_params);

    // Delete the parameters.
    D.getFunctionTypeInfo().freeParams();
    D.setInvalidType();
  } else if (Proto->isVariadic()) {
    Diag(D.getIdentifierLoc(), diag::err_conv_function_variadic);
    D.setInvalidType();
  }

  // Diagnose "&operator bool()" and other such nonsense.  This
  // is actually a gcc extension which we don't support.
  if (Proto->getReturnType() != ConvType) {
    bool NeedsTypedef = false;
    SourceRange Before, After;

    // Walk the chunks and extract information on them for our diagnostic.
    bool PastFunctionChunk = false;
    for (auto &Chunk : D.type_objects()) {
      switch (Chunk.Kind) {
      case DeclaratorChunk::Function:
        if (!PastFunctionChunk) {
          if (Chunk.Fun.HasTrailingReturnType) {
            TypeSourceInfo *TRT = nullptr;
            GetTypeFromParser(Chunk.Fun.getTrailingReturnType(), &TRT);
            if (TRT) extendRight(After, TRT->getTypeLoc().getSourceRange());
          }
          PastFunctionChunk = true;
          break;
        }
        LLVM_FALLTHROUGH;
      case DeclaratorChunk::Array:
        NeedsTypedef = true;
        extendRight(After, Chunk.getSourceRange());
        break;

      case DeclaratorChunk::Pointer:
      case DeclaratorChunk::BlockPointer:
      case DeclaratorChunk::Reference:
      case DeclaratorChunk::MemberPointer:
      case DeclaratorChunk::Pipe:
        extendLeft(Before, Chunk.getSourceRange());
        break;

      case DeclaratorChunk::Paren:
        extendLeft(Before, Chunk.Loc);
        extendRight(After, Chunk.EndLoc);
        break;
      }
    }

    SourceLocation Loc = Before.isValid() ? Before.getBegin() :
                         After.isValid()  ? After.getBegin() :
                                            D.getIdentifierLoc();
    auto &&DB = Diag(Loc, diag::err_conv_function_with_complex_decl);
    DB << Before << After;

    if (!NeedsTypedef) {
      DB << /*don't need a typedef*/0;

      // If we can provide a correct fix-it hint, do so.
      if (After.isInvalid() && ConvTSI) {
        SourceLocation InsertLoc =
            getLocForEndOfToken(ConvTSI->getTypeLoc().getEndLoc());
        DB << FixItHint::CreateInsertion(InsertLoc, " ")
           << FixItHint::CreateInsertionFromRange(
                  InsertLoc, CharSourceRange::getTokenRange(Before))
           << FixItHint::CreateRemoval(Before);
      }
    } else if (!Proto->getReturnType()->isDependentType()) {
      DB << /*typedef*/1 << Proto->getReturnType();
    } else if (getLangOpts().CPlusPlus11) {
      DB << /*alias template*/2 << Proto->getReturnType();
    } else {
      DB << /*might not be fixable*/3;
    }

    // Recover by incorporating the other type chunks into the result type.
    // Note, this does *not* change the name of the function. This is compatible
    // with the GCC extension:
    //   struct S { &operator int(); } s;
    //   int &r = s.operator int(); // ok in GCC
    //   S::operator int&() {} // error in GCC, function name is 'operator int'.
    ConvType = Proto->getReturnType();
  }

  // C++ [class.conv.fct]p4:
  //   The conversion-type-id shall not represent a function type nor
  //   an array type.
  if (ConvType->isArrayType()) {
    Diag(D.getIdentifierLoc(), diag::err_conv_function_to_array);
    ConvType = Context.getPointerType(ConvType);
    D.setInvalidType();
  } else if (ConvType->isFunctionType()) {
    Diag(D.getIdentifierLoc(), diag::err_conv_function_to_function);
    ConvType = Context.getPointerType(ConvType);
    D.setInvalidType();
  }

  // Rebuild the function type "R" without any parameters (in case any
  // of the errors above fired) and with the conversion type as the
  // return type.
  if (D.isInvalidType())
    R = Context.getFunctionType(ConvType, None, Proto->getExtProtoInfo());

  // C++0x explicit conversion operators.
  if (DS.hasExplicitSpecifier() && !getLangOpts().CPlusPlus2a)
    Diag(DS.getExplicitSpecLoc(),
         getLangOpts().CPlusPlus11
             ? diag::warn_cxx98_compat_explicit_conversion_functions
             : diag::ext_explicit_conversion_functions)
        << SourceRange(DS.getExplicitSpecRange());
}

/// ActOnConversionDeclarator - Called by ActOnDeclarator to complete
/// the declaration of the given C++ conversion function. This routine
/// is responsible for recording the conversion function in the C++
/// class, if possible.
Decl *Sema::ActOnConversionDeclarator(CXXConversionDecl *Conversion) {
  assert(Conversion && "Expected to receive a conversion function declaration");

  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Conversion->getDeclContext());

  // Make sure we aren't redeclaring the conversion function.
  QualType ConvType = Context.getCanonicalType(Conversion->getConversionType());

  // C++ [class.conv.fct]p1:
  //   [...] A conversion function is never used to convert a
  //   (possibly cv-qualified) object to the (possibly cv-qualified)
  //   same object type (or a reference to it), to a (possibly
  //   cv-qualified) base class of that type (or a reference to it),
  //   or to (possibly cv-qualified) void.
  // FIXME: Suppress this warning if the conversion function ends up being a
  // virtual function that overrides a virtual function in a base class.
  QualType ClassType
    = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
  if (const ReferenceType *ConvTypeRef = ConvType->getAs<ReferenceType>())
    ConvType = ConvTypeRef->getPointeeType();
  if (Conversion->getTemplateSpecializationKind() != TSK_Undeclared &&
      Conversion->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
    /* Suppress diagnostics for instantiations. */;
  else if (ConvType->isRecordType()) {
    ConvType = Context.getCanonicalType(ConvType).getUnqualifiedType();
    if (ConvType == ClassType)
      Diag(Conversion->getLocation(), diag::warn_conv_to_self_not_used)
        << ClassType;
    else if (IsDerivedFrom(Conversion->getLocation(), ClassType, ConvType))
      Diag(Conversion->getLocation(), diag::warn_conv_to_base_not_used)
        <<  ClassType << ConvType;
  } else if (ConvType->isVoidType()) {
    Diag(Conversion->getLocation(), diag::warn_conv_to_void_not_used)
      << ClassType << ConvType;
  }

  if (FunctionTemplateDecl *ConversionTemplate
                                = Conversion->getDescribedFunctionTemplate())
    return ConversionTemplate;

  return Conversion;
}

namespace {
/// Utility class to accumulate and print a diagnostic listing the invalid
/// specifier(s) on a declaration.
struct BadSpecifierDiagnoser {
  BadSpecifierDiagnoser(Sema &S, SourceLocation Loc, unsigned DiagID)
      : S(S), Diagnostic(S.Diag(Loc, DiagID)) {}
  ~BadSpecifierDiagnoser() {
    Diagnostic << Specifiers;
  }

  template<typename T> void check(SourceLocation SpecLoc, T Spec) {
    return check(SpecLoc, DeclSpec::getSpecifierName(Spec));
  }
  void check(SourceLocation SpecLoc, DeclSpec::TST Spec) {
    return check(SpecLoc,
                 DeclSpec::getSpecifierName(Spec, S.getPrintingPolicy()));
  }
  void check(SourceLocation SpecLoc, const char *Spec) {
    if (SpecLoc.isInvalid()) return;
    Diagnostic << SourceRange(SpecLoc, SpecLoc);
    if (!Specifiers.empty()) Specifiers += " ";
    Specifiers += Spec;
  }

  Sema &S;
  Sema::SemaDiagnosticBuilder Diagnostic;
  std::string Specifiers;
};
}

/// Check the validity of a declarator that we parsed for a deduction-guide.
/// These aren't actually declarators in the grammar, so we need to check that
/// the user didn't specify any pieces that are not part of the deduction-guide
/// grammar.
void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
                                         StorageClass &SC) {
  TemplateName GuidedTemplate = D.getName().TemplateName.get().get();
  TemplateDecl *GuidedTemplateDecl = GuidedTemplate.getAsTemplateDecl();
  assert(GuidedTemplateDecl && "missing template decl for deduction guide");

  // C++ [temp.deduct.guide]p3:
  //   A deduction-gide shall be declared in the same scope as the
  //   corresponding class template.
  if (!CurContext->getRedeclContext()->Equals(
          GuidedTemplateDecl->getDeclContext()->getRedeclContext())) {
    Diag(D.getIdentifierLoc(), diag::err_deduction_guide_wrong_scope)
      << GuidedTemplateDecl;
    Diag(GuidedTemplateDecl->getLocation(), diag::note_template_decl_here);
  }

  auto &DS = D.getMutableDeclSpec();
  // We leave 'friend' and 'virtual' to be rejected in the normal way.
  if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() ||
      DS.getStorageClassSpecLoc().isValid() || DS.isInlineSpecified() ||
      DS.isNoreturnSpecified() || DS.isConstexprSpecified()) {
    BadSpecifierDiagnoser Diagnoser(
        *this, D.getIdentifierLoc(),
        diag::err_deduction_guide_invalid_specifier);

    Diagnoser.check(DS.getStorageClassSpecLoc(), DS.getStorageClassSpec());
    DS.ClearStorageClassSpecs();
    SC = SC_None;

    // 'explicit' is permitted.
    Diagnoser.check(DS.getInlineSpecLoc(), "inline");
    Diagnoser.check(DS.getNoreturnSpecLoc(), "_Noreturn");
    Diagnoser.check(DS.getConstexprSpecLoc(), "constexpr");
    DS.ClearConstexprSpec();

    Diagnoser.check(DS.getConstSpecLoc(), "const");
    Diagnoser.check(DS.getRestrictSpecLoc(), "__restrict");
    Diagnoser.check(DS.getVolatileSpecLoc(), "volatile");
    Diagnoser.check(DS.getAtomicSpecLoc(), "_Atomic");
    Diagnoser.check(DS.getUnalignedSpecLoc(), "__unaligned");
    DS.ClearTypeQualifiers();

    Diagnoser.check(DS.getTypeSpecComplexLoc(), DS.getTypeSpecComplex());
    Diagnoser.check(DS.getTypeSpecSignLoc(), DS.getTypeSpecSign());
    Diagnoser.check(DS.getTypeSpecWidthLoc(), DS.getTypeSpecWidth());
    Diagnoser.check(DS.getTypeSpecTypeLoc(), DS.getTypeSpecType());
    DS.ClearTypeSpecType();
  }

  if (D.isInvalidType())
    return;

  // Check the declarator is simple enough.
  bool FoundFunction = false;
  for (const DeclaratorChunk &Chunk : llvm::reverse(D.type_objects())) {
    if (Chunk.Kind == DeclaratorChunk::Paren)
      continue;
    if (Chunk.Kind != DeclaratorChunk::Function || FoundFunction) {
      Diag(D.getDeclSpec().getBeginLoc(),
           diag::err_deduction_guide_with_complex_decl)
          << D.getSourceRange();
      break;
    }
    if (!Chunk.Fun.hasTrailingReturnType()) {
      Diag(D.getName().getBeginLoc(),
           diag::err_deduction_guide_no_trailing_return_type);
      break;
    }

    // Check that the return type is written as a specialization of
    // the template specified as the deduction-guide's name.
    ParsedType TrailingReturnType = Chunk.Fun.getTrailingReturnType();
    TypeSourceInfo *TSI = nullptr;
    QualType RetTy = GetTypeFromParser(TrailingReturnType, &TSI);
    assert(TSI && "deduction guide has valid type but invalid return type?");
    bool AcceptableReturnType = false;
    bool MightInstantiateToSpecialization = false;
    if (auto RetTST =
            TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>()) {
      TemplateName SpecifiedName = RetTST.getTypePtr()->getTemplateName();
      bool TemplateMatches =
          Context.hasSameTemplateName(SpecifiedName, GuidedTemplate);
      if (SpecifiedName.getKind() == TemplateName::Template && TemplateMatches)
        AcceptableReturnType = true;
      else {
        // This could still instantiate to the right type, unless we know it
        // names the wrong class template.
        auto *TD = SpecifiedName.getAsTemplateDecl();
        MightInstantiateToSpecialization = !(TD && isa<ClassTemplateDecl>(TD) &&
                                             !TemplateMatches);
      }
    } else if (!RetTy.hasQualifiers() && RetTy->isDependentType()) {
      MightInstantiateToSpecialization = true;
    }

    if (!AcceptableReturnType) {
      Diag(TSI->getTypeLoc().getBeginLoc(),
           diag::err_deduction_guide_bad_trailing_return_type)
          << GuidedTemplate << TSI->getType()
          << MightInstantiateToSpecialization
          << TSI->getTypeLoc().getSourceRange();
    }

    // Keep going to check that we don't have any inner declarator pieces (we
    // could still have a function returning a pointer to a function).
    FoundFunction = true;
  }

  if (D.isFunctionDefinition())
    Diag(D.getIdentifierLoc(), diag::err_deduction_guide_defines_function);
}

//===----------------------------------------------------------------------===//
// Namespace Handling
//===----------------------------------------------------------------------===//

/// Diagnose a mismatch in 'inline' qualifiers when a namespace is
/// reopened.
static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc,
                                            SourceLocation Loc,
                                            IdentifierInfo *II, bool *IsInline,
                                            NamespaceDecl *PrevNS) {
  assert(*IsInline != PrevNS->isInline());

  // HACK: Work around a bug in libstdc++4.6's <atomic>, where
  // std::__atomic[0,1,2] are defined as non-inline namespaces, then reopened as
  // inline namespaces, with the intention of bringing names into namespace std.
  //
  // We support this just well enough to get that case working; this is not
  // sufficient to support reopening namespaces as inline in general.
  if (*IsInline && II && II->getName().startswith("__atomic") &&
      S.getSourceManager().isInSystemHeader(Loc)) {
    // Mark all prior declarations of the namespace as inline.
    for (NamespaceDecl *NS = PrevNS->getMostRecentDecl(); NS;
         NS = NS->getPreviousDecl())
      NS->setInline(*IsInline);
    // Patch up the lookup table for the containing namespace. This isn't really
    // correct, but it's good enough for this particular case.
    for (auto *I : PrevNS->decls())
      if (auto *ND = dyn_cast<NamedDecl>(I))
        PrevNS->getParent()->makeDeclVisibleInContext(ND);
    return;
  }

  if (PrevNS->isInline())
    // The user probably just forgot the 'inline', so suggest that it
    // be added back.
    S.Diag(Loc, diag::warn_inline_namespace_reopened_noninline)
      << FixItHint::CreateInsertion(KeywordLoc, "inline ");
  else
    S.Diag(Loc, diag::err_inline_namespace_mismatch);

  S.Diag(PrevNS->getLocation(), diag::note_previous_definition);
  *IsInline = PrevNS->isInline();
}

/// ActOnStartNamespaceDef - This is called at the start of a namespace
/// definition.
Decl *Sema::ActOnStartNamespaceDef(
    Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc,
    SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace,
    const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) {
  SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
  // For anonymous namespace, take the location of the left brace.
  SourceLocation Loc = II ? IdentLoc : LBrace;
  bool IsInline = InlineLoc.isValid();
  bool IsInvalid = false;
  bool IsStd = false;
  bool AddToKnown = false;
  Scope *DeclRegionScope = NamespcScope->getParent();

  NamespaceDecl *PrevNS = nullptr;
  if (II) {
    // C++ [namespace.def]p2:
    //   The identifier in an original-namespace-definition shall not
    //   have been previously defined in the declarative region in
    //   which the original-namespace-definition appears. The
    //   identifier in an original-namespace-definition is the name of
    //   the namespace. Subsequently in that declarative region, it is
    //   treated as an original-namespace-name.
    //
    // Since namespace names are unique in their scope, and we don't
    // look through using directives, just look for any ordinary names
    // as if by qualified name lookup.
    LookupResult R(*this, II, IdentLoc, LookupOrdinaryName,
                   ForExternalRedeclaration);
    LookupQualifiedName(R, CurContext->getRedeclContext());
    NamedDecl *PrevDecl =
        R.isSingleResult() ? R.getRepresentativeDecl() : nullptr;
    PrevNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl);

    if (PrevNS) {
      // This is an extended namespace definition.
      if (IsInline != PrevNS->isInline())
        DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, Loc, II,
                                        &IsInline, PrevNS);
    } else if (PrevDecl) {
      // This is an invalid name redefinition.
      Diag(Loc, diag::err_redefinition_different_kind)
        << II;
      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
      IsInvalid = true;
      // Continue on to push Namespc as current DeclContext and return it.
    } else if (II->isStr("std") &&
               CurContext->getRedeclContext()->isTranslationUnit()) {
      // This is the first "real" definition of the namespace "std", so update
      // our cache of the "std" namespace to point at this definition.
      PrevNS = getStdNamespace();
      IsStd = true;
      AddToKnown = !IsInline;
    } else {
      // We've seen this namespace for the first time.
      AddToKnown = !IsInline;
    }
  } else {
    // Anonymous namespaces.

    // Determine whether the parent already has an anonymous namespace.
    DeclContext *Parent = CurContext->getRedeclContext();
    if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
      PrevNS = TU->getAnonymousNamespace();
    } else {
      NamespaceDecl *ND = cast<NamespaceDecl>(Parent);
      PrevNS = ND->getAnonymousNamespace();
    }

    if (PrevNS && IsInline != PrevNS->isInline())
      DiagnoseNamespaceInlineMismatch(*this, NamespaceLoc, NamespaceLoc, II,
                                      &IsInline, PrevNS);
  }

  NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline,
                                                 StartLoc, Loc, II, PrevNS);
  if (IsInvalid)
    Namespc->setInvalidDecl();

  ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
  AddPragmaAttributes(DeclRegionScope, Namespc);

  // FIXME: Should we be merging attributes?
  if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
    PushNamespaceVisibilityAttr(Attr, Loc);

  if (IsStd)
    StdNamespace = Namespc;
  if (AddToKnown)
    KnownNamespaces[Namespc] = false;

  if (II) {
    PushOnScopeChains(Namespc, DeclRegionScope);
  } else {
    // Link the anonymous namespace into its parent.
    DeclContext *Parent = CurContext->getRedeclContext();
    if (TranslationUnitDecl *TU = dyn_cast<TranslationUnitDecl>(Parent)) {
      TU->setAnonymousNamespace(Namespc);
    } else {
      cast<NamespaceDecl>(Parent)->setAnonymousNamespace(Namespc);
    }

    CurContext->addDecl(Namespc);

    // C++ [namespace.unnamed]p1.  An unnamed-namespace-definition
    //   behaves as if it were replaced by
    //     namespace unique { /* empty body */ }
    //     using namespace unique;
    //     namespace unique { namespace-body }
    //   where all occurrences of 'unique' in a translation unit are
    //   replaced by the same identifier and this identifier differs
    //   from all other identifiers in the entire program.

    // We just create the namespace with an empty name and then add an
    // implicit using declaration, just like the standard suggests.
    //
    // CodeGen enforces the "universally unique" aspect by giving all
    // declarations semantically contained within an anonymous
    // namespace internal linkage.

    if (!PrevNS) {
      UD = UsingDirectiveDecl::Create(Context, Parent,
                                      /* 'using' */ LBrace,
                                      /* 'namespace' */ SourceLocation(),
                                      /* qualifier */ NestedNameSpecifierLoc(),
                                      /* identifier */ SourceLocation(),
                                      Namespc,
                                      /* Ancestor */ Parent);
      UD->setImplicit();
      Parent->addDecl(UD);
    }
  }

  ActOnDocumentableDecl(Namespc);

  // Although we could have an invalid decl (i.e. the namespace name is a
  // redefinition), push it as current DeclContext and try to continue parsing.
  // FIXME: We should be able to push Namespc here, so that the each DeclContext
  // for the namespace has the declarations that showed up in that particular
  // namespace definition.
  PushDeclContext(NamespcScope, Namespc);
  return Namespc;
}

/// getNamespaceDecl - Returns the namespace a decl represents. If the decl
/// is a namespace alias, returns the namespace it points to.
static inline NamespaceDecl *getNamespaceDecl(NamedDecl *D) {
  if (NamespaceAliasDecl *AD = dyn_cast_or_null<NamespaceAliasDecl>(D))
    return AD->getNamespace();
  return dyn_cast_or_null<NamespaceDecl>(D);
}

/// ActOnFinishNamespaceDef - This callback is called after a namespace is
/// exited. Decl is the DeclTy returned by ActOnStartNamespaceDef.
void Sema::ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace) {
  NamespaceDecl *Namespc = dyn_cast_or_null<NamespaceDecl>(Dcl);
  assert(Namespc && "Invalid parameter, expected NamespaceDecl");
  Namespc->setRBraceLoc(RBrace);
  PopDeclContext();
  if (Namespc->hasAttr<VisibilityAttr>())
    PopPragmaVisibility(true, RBrace);
  // If this namespace contains an export-declaration, export it now.
  if (DeferredExportedNamespaces.erase(Namespc))
    Dcl->setModuleOwnershipKind(Decl::ModuleOwnershipKind::VisibleWhenImported);
}

CXXRecordDecl *Sema::getStdBadAlloc() const {
  return cast_or_null<CXXRecordDecl>(
                                  StdBadAlloc.get(Context.getExternalSource()));
}

EnumDecl *Sema::getStdAlignValT() const {
  return cast_or_null<EnumDecl>(StdAlignValT.get(Context.getExternalSource()));
}

NamespaceDecl *Sema::getStdNamespace() const {
  return cast_or_null<NamespaceDecl>(
                                 StdNamespace.get(Context.getExternalSource()));
}

NamespaceDecl *Sema::lookupStdExperimentalNamespace() {
  if (!StdExperimentalNamespaceCache) {
    if (auto Std = getStdNamespace()) {
      LookupResult Result(*this, &PP.getIdentifierTable().get("experimental"),
                          SourceLocation(), LookupNamespaceName);
      if (!LookupQualifiedName(Result, Std) ||
          !(StdExperimentalNamespaceCache =
                Result.getAsSingle<NamespaceDecl>()))
        Result.suppressDiagnostics();
    }
  }
  return StdExperimentalNamespaceCache;
}

namespace {

enum UnsupportedSTLSelect {
  USS_InvalidMember,
  USS_MissingMember,
  USS_NonTrivial,
  USS_Other
};

struct InvalidSTLDiagnoser {
  Sema &S;
  SourceLocation Loc;
  QualType TyForDiags;

  QualType operator()(UnsupportedSTLSelect Sel = USS_Other, StringRef Name = "",
                      const VarDecl *VD = nullptr) {
    {
      auto D = S.Diag(Loc, diag::err_std_compare_type_not_supported)
               << TyForDiags << ((int)Sel);
      if (Sel == USS_InvalidMember || Sel == USS_MissingMember) {
        assert(!Name.empty());
        D << Name;
      }
    }
    if (Sel == USS_InvalidMember) {
      S.Diag(VD->getLocation(), diag::note_var_declared_here)
          << VD << VD->getSourceRange();
    }
    return QualType();
  }
};
} // namespace

QualType Sema::CheckComparisonCategoryType(ComparisonCategoryType Kind,
                                           SourceLocation Loc) {
  assert(getLangOpts().CPlusPlus &&
         "Looking for comparison category type outside of C++.");

  // Check if we've already successfully checked the comparison category type
  // before. If so, skip checking it again.
  ComparisonCategoryInfo *Info = Context.CompCategories.lookupInfo(Kind);
  if (Info && FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)])
    return Info->getType();

  // If lookup failed
  if (!Info) {
    std::string NameForDiags = "std::";
    NameForDiags += ComparisonCategories::getCategoryString(Kind);
    Diag(Loc, diag::err_implied_comparison_category_type_not_found)
        << NameForDiags;
    return QualType();
  }

  assert(Info->Kind == Kind);
  assert(Info->Record);

  // Update the Record decl in case we encountered a forward declaration on our
  // first pass. FIXME: This is a bit of a hack.
  if (Info->Record->hasDefinition())
    Info->Record = Info->Record->getDefinition();

  // Use an elaborated type for diagnostics which has a name containing the
  // prepended 'std' namespace but not any inline namespace names.
  QualType TyForDiags = [&]() {
    auto *NNS =
        NestedNameSpecifier::Create(Context, nullptr, getStdNamespace());
    return Context.getElaboratedType(ETK_None, NNS, Info->getType());
  }();

  if (RequireCompleteType(Loc, TyForDiags, diag::err_incomplete_type))
    return QualType();

  InvalidSTLDiagnoser UnsupportedSTLError{*this, Loc, TyForDiags};

  if (!Info->Record->isTriviallyCopyable())
    return UnsupportedSTLError(USS_NonTrivial);

  for (const CXXBaseSpecifier &BaseSpec : Info->Record->bases()) {
    CXXRecordDecl *Base = BaseSpec.getType()->getAsCXXRecordDecl();
    // Tolerate empty base classes.
    if (Base->isEmpty())
      continue;
    // Reject STL implementations which have at least one non-empty base.
    return UnsupportedSTLError();
  }

  // Check that the STL has implemented the types using a single integer field.
  // This expectation allows better codegen for builtin operators. We require:
  //   (1) The class has exactly one field.
  //   (2) The field is an integral or enumeration type.
  auto FIt = Info->Record->field_begin(), FEnd = Info->Record->field_end();
  if (std::distance(FIt, FEnd) != 1 ||
      !FIt->getType()->isIntegralOrEnumerationType()) {
    return UnsupportedSTLError();
  }

  // Build each of the require values and store them in Info.
  for (ComparisonCategoryResult CCR :
       ComparisonCategories::getPossibleResultsForType(Kind)) {
    StringRef MemName = ComparisonCategories::getResultString(CCR);
    ComparisonCategoryInfo::ValueInfo *ValInfo = Info->lookupValueInfo(CCR);

    if (!ValInfo)
      return UnsupportedSTLError(USS_MissingMember, MemName);

    VarDecl *VD = ValInfo->VD;
    assert(VD && "should not be null!");

    // Attempt to diagnose reasons why the STL definition of this type
    // might be foobar, including it failing to be a constant expression.
    // TODO Handle more ways the lookup or result can be invalid.
    if (!VD->isStaticDataMember() || !VD->isConstexpr() || !VD->hasInit() ||
        !VD->checkInitIsICE())
      return UnsupportedSTLError(USS_InvalidMember, MemName, VD);

    // Attempt to evaluate the var decl as a constant expression and extract
    // the value of its first field as a ICE. If this fails, the STL
    // implementation is not supported.
    if (!ValInfo->hasValidIntValue())
      return UnsupportedSTLError();

    MarkVariableReferenced(Loc, VD);
  }

  // We've successfully built the required types and expressions. Update
  // the cache and return the newly cached value.
  FullyCheckedComparisonCategories[static_cast<unsigned>(Kind)] = true;
  return Info->getType();
}

/// Retrieve the special "std" namespace, which may require us to
/// implicitly define the namespace.
NamespaceDecl *Sema::getOrCreateStdNamespace() {
  if (!StdNamespace) {
    // The "std" namespace has not yet been defined, so build one implicitly.
    StdNamespace = NamespaceDecl::Create(Context,
                                         Context.getTranslationUnitDecl(),
                                         /*Inline=*/false,
                                         SourceLocation(), SourceLocation(),
                                         &PP.getIdentifierTable().get("std"),
                                         /*PrevDecl=*/nullptr);
    getStdNamespace()->setImplicit(true);
  }

  return getStdNamespace();
}

bool Sema::isStdInitializerList(QualType Ty, QualType *Element) {
  assert(getLangOpts().CPlusPlus &&
         "Looking for std::initializer_list outside of C++.");

  // We're looking for implicit instantiations of
  // template <typename E> class std::initializer_list.

  if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it.
    return false;

  ClassTemplateDecl *Template = nullptr;
  const TemplateArgument *Arguments = nullptr;

  if (const RecordType *RT = Ty->getAs<RecordType>()) {

    ClassTemplateSpecializationDecl *Specialization =
        dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
    if (!Specialization)
      return false;

    Template = Specialization->getSpecializedTemplate();
    Arguments = Specialization->getTemplateArgs().data();
  } else if (const TemplateSpecializationType *TST =
                 Ty->getAs<TemplateSpecializationType>()) {
    Template = dyn_cast_or_null<ClassTemplateDecl>(
        TST->getTemplateName().getAsTemplateDecl());
    Arguments = TST->getArgs();
  }
  if (!Template)
    return false;

  if (!StdInitializerList) {
    // Haven't recognized std::initializer_list yet, maybe this is it.
    CXXRecordDecl *TemplateClass = Template->getTemplatedDecl();
    if (TemplateClass->getIdentifier() !=
            &PP.getIdentifierTable().get("initializer_list") ||
        !getStdNamespace()->InEnclosingNamespaceSetOf(
            TemplateClass->getDeclContext()))
      return false;
    // This is a template called std::initializer_list, but is it the right
    // template?
    TemplateParameterList *Params = Template->getTemplateParameters();
    if (Params->getMinRequiredArguments() != 1)
      return false;
    if (!isa<TemplateTypeParmDecl>(Params->getParam(0)))
      return false;

    // It's the right template.
    StdInitializerList = Template;
  }

  if (Template->getCanonicalDecl() != StdInitializerList->getCanonicalDecl())
    return false;

  // This is an instance of std::initializer_list. Find the argument type.
  if (Element)
    *Element = Arguments[0].getAsType();
  return true;
}

static ClassTemplateDecl *LookupStdInitializerList(Sema &S, SourceLocation Loc){
  NamespaceDecl *Std = S.getStdNamespace();
  if (!Std) {
    S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
    return nullptr;
  }

  LookupResult Result(S, &S.PP.getIdentifierTable().get("initializer_list"),
                      Loc, Sema::LookupOrdinaryName);
  if (!S.LookupQualifiedName(Result, Std)) {
    S.Diag(Loc, diag::err_implied_std_initializer_list_not_found);
    return nullptr;
  }
  ClassTemplateDecl *Template = Result.getAsSingle<ClassTemplateDecl>();
  if (!Template) {
    Result.suppressDiagnostics();
    // We found something weird. Complain about the first thing we found.
    NamedDecl *Found = *Result.begin();
    S.Diag(Found->getLocation(), diag::err_malformed_std_initializer_list);
    return nullptr;
  }

  // We found some template called std::initializer_list. Now verify that it's
  // correct.
  TemplateParameterList *Params = Template->getTemplateParameters();
  if (Params->getMinRequiredArguments() != 1 ||
      !isa<TemplateTypeParmDecl>(Params->getParam(0))) {
    S.Diag(Template->getLocation(), diag::err_malformed_std_initializer_list);
    return nullptr;
  }

  return Template;
}

QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) {
  if (!StdInitializerList) {
    StdInitializerList = LookupStdInitializerList(*this, Loc);
    if (!StdInitializerList)
      return QualType();
  }

  TemplateArgumentListInfo Args(Loc, Loc);
  Args.addArgument(TemplateArgumentLoc(TemplateArgument(Element),
                                       Context.getTrivialTypeSourceInfo(Element,
                                                                        Loc)));
  return Context.getCanonicalType(
      CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args));
}

bool Sema::isInitListConstructor(const FunctionDecl *Ctor) {
  // C++ [dcl.init.list]p2:
  //   A constructor is an initializer-list constructor if its first parameter
  //   is of type std::initializer_list<E> or reference to possibly cv-qualified
  //   std::initializer_list<E> for some type E, and either there are no other
  //   parameters or else all other parameters have default arguments.
  if (Ctor->getNumParams() < 1 ||
      (Ctor->getNumParams() > 1 && !Ctor->getParamDecl(1)->hasDefaultArg()))
    return false;

  QualType ArgType = Ctor->getParamDecl(0)->getType();
  if (const ReferenceType *RT = ArgType->getAs<ReferenceType>())
    ArgType = RT->getPointeeType().getUnqualifiedType();

  return isStdInitializerList(ArgType, nullptr);
}

/// Determine whether a using statement is in a context where it will be
/// apply in all contexts.
static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) {
  switch (CurContext->getDeclKind()) {
    case Decl::TranslationUnit:
      return true;
    case Decl::LinkageSpec:
      return IsUsingDirectiveInToplevelContext(CurContext->getParent());
    default:
      return false;
  }
}

namespace {

// Callback to only accept typo corrections that are namespaces.
class NamespaceValidatorCCC final : public CorrectionCandidateCallback {
public:
  bool ValidateCandidate(const TypoCorrection &candidate) override {
    if (NamedDecl *ND = candidate.getCorrectionDecl())
      return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
    return false;
  }

  std::unique_ptr<CorrectionCandidateCallback> clone() override {
    return llvm::make_unique<NamespaceValidatorCCC>(*this);
  }
};

}

static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
                                       CXXScopeSpec &SS,
                                       SourceLocation IdentLoc,
                                       IdentifierInfo *Ident) {
  R.clear();
  NamespaceValidatorCCC CCC{};
  if (TypoCorrection Corrected =
          S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS, CCC,
                        Sema::CTK_ErrorRecovery)) {
    if (DeclContext *DC = S.computeDeclContext(SS, false)) {
      std::string CorrectedStr(Corrected.getAsString(S.getLangOpts()));
      bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
                              Ident->getName().equals(CorrectedStr);
      S.diagnoseTypo(Corrected,
                     S.PDiag(diag::err_using_directive_member_suggest)
                       << Ident << DC << DroppedSpecifier << SS.getRange(),
                     S.PDiag(diag::note_namespace_defined_here));
    } else {
      S.diagnoseTypo(Corrected,
                     S.PDiag(diag::err_using_directive_suggest) << Ident,
                     S.PDiag(diag::note_namespace_defined_here));
    }
    R.addDecl(Corrected.getFoundDecl());
    return true;
  }
  return false;
}

Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,
                                SourceLocation NamespcLoc, CXXScopeSpec &SS,
                                SourceLocation IdentLoc,
                                IdentifierInfo *NamespcName,
                                const ParsedAttributesView &AttrList) {
  assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
  assert(NamespcName && "Invalid NamespcName.");
  assert(IdentLoc.isValid() && "Invalid NamespceName location.");

  // This can only happen along a recovery path.
  while (S->isTemplateParamScope())
    S = S->getParent();
  assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");

  UsingDirectiveDecl *UDir = nullptr;
  NestedNameSpecifier *Qualifier = nullptr;
  if (SS.isSet())
    Qualifier = SS.getScopeRep();

  // Lookup namespace name.
  LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
  LookupParsedName(R, S, &SS);
  if (R.isAmbiguous())
    return nullptr;

  if (R.empty()) {
    R.clear();
    // Allow "using namespace std;" or "using namespace ::std;" even if
    // "std" hasn't been defined yet, for GCC compatibility.
    if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&
        NamespcName->isStr("std")) {
      Diag(IdentLoc, diag::ext_using_undefined_std);
      R.addDecl(getOrCreateStdNamespace());
      R.resolveKind();
    }
    // Otherwise, attempt typo correction.
    else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);
  }

  if (!R.empty()) {
    NamedDecl *Named = R.getRepresentativeDecl();
    NamespaceDecl *NS = R.getAsSingle<NamespaceDecl>();
    assert(NS && "expected namespace decl");

    // The use of a nested name specifier may trigger deprecation warnings.
    DiagnoseUseOfDecl(Named, IdentLoc);

    // C++ [namespace.udir]p1:
    //   A using-directive specifies that the names in the nominated
    //   namespace can be used in the scope in which the
    //   using-directive appears after the using-directive. During
    //   unqualified name lookup (3.4.1), the names appear as if they
    //   were declared in the nearest enclosing namespace which
    //   contains both the using-directive and the nominated
    //   namespace. [Note: in this context, "contains" means "contains
    //   directly or indirectly". ]

    // Find enclosing context containing both using-directive and
    // nominated namespace.
    DeclContext *CommonAncestor = NS;
    while (CommonAncestor && !CommonAncestor->Encloses(CurContext))
      CommonAncestor = CommonAncestor->getParent();

    UDir = UsingDirectiveDecl::Create(Context, CurContext, UsingLoc, NamespcLoc,
                                      SS.getWithLocInContext(Context),
                                      IdentLoc, Named, CommonAncestor);

    if (IsUsingDirectiveInToplevelContext(CurContext) &&
        !SourceMgr.isInMainFile(SourceMgr.getExpansionLoc(IdentLoc))) {
      Diag(IdentLoc, diag::warn_using_directive_in_header);
    }

    PushUsingDirective(S, UDir);
  } else {
    Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
  }

  if (UDir)
    ProcessDeclAttributeList(S, UDir, AttrList);

  return UDir;
}

void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) {
  // If the scope has an associated entity and the using directive is at
  // namespace or translation unit scope, add the UsingDirectiveDecl into
  // its lookup structure so qualified name lookup can find it.
  DeclContext *Ctx = S->getEntity();
  if (Ctx && !Ctx->isFunctionOrMethod())
    Ctx->addDecl(UDir);
  else
    // Otherwise, it is at block scope. The using-directives will affect lookup
    // only to the end of the scope.
    S->PushUsingDirective(UDir);
}

Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS,
                                  SourceLocation UsingLoc,
                                  SourceLocation TypenameLoc, CXXScopeSpec &SS,
                                  UnqualifiedId &Name,
                                  SourceLocation EllipsisLoc,
                                  const ParsedAttributesView &AttrList) {
  assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");

  if (SS.isEmpty()) {
    Diag(Name.getBeginLoc(), diag::err_using_requires_qualname);
    return nullptr;
  }

  switch (Name.getKind()) {
  case UnqualifiedIdKind::IK_ImplicitSelfParam:
  case UnqualifiedIdKind::IK_Identifier:
  case UnqualifiedIdKind::IK_OperatorFunctionId:
  case UnqualifiedIdKind::IK_LiteralOperatorId:
  case UnqualifiedIdKind::IK_ConversionFunctionId:
    break;

  case UnqualifiedIdKind::IK_ConstructorName:
  case UnqualifiedIdKind::IK_ConstructorTemplateId:
    // C++11 inheriting constructors.
    Diag(Name.getBeginLoc(),
         getLangOpts().CPlusPlus11
             ? diag::warn_cxx98_compat_using_decl_constructor
             : diag::err_using_decl_constructor)
        << SS.getRange();

    if (getLangOpts().CPlusPlus11) break;

    return nullptr;

  case UnqualifiedIdKind::IK_DestructorName:
    Diag(Name.getBeginLoc(), diag::err_using_decl_destructor) << SS.getRange();
    return nullptr;

  case UnqualifiedIdKind::IK_TemplateId:
    Diag(Name.getBeginLoc(), diag::err_using_decl_template_id)
        << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
    return nullptr;

  case UnqualifiedIdKind::IK_DeductionGuideName:
    llvm_unreachable("cannot parse qualified deduction guide name");
  }

  DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
  DeclarationName TargetName = TargetNameInfo.getName();
  if (!TargetName)
    return nullptr;

  // Warn about access declarations.
  if (UsingLoc.isInvalid()) {
    Diag(Name.getBeginLoc(), getLangOpts().CPlusPlus11
                                 ? diag::err_access_decl
                                 : diag::warn_access_decl_deprecated)
        << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
  }

  if (EllipsisLoc.isInvalid()) {
    if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
        DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
      return nullptr;
  } else {
    if (!SS.getScopeRep()->containsUnexpandedParameterPack() &&
        !TargetNameInfo.containsUnexpandedParameterPack()) {
      Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
        << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc());
      EllipsisLoc = SourceLocation();
    }
  }

  NamedDecl *UD =
      BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc,
                            SS, TargetNameInfo, EllipsisLoc, AttrList,
                            /*IsInstantiation*/false);
  if (UD)
    PushOnScopeChains(UD, S, /*AddToContext*/ false);

  return UD;
}

/// Determine whether a using declaration considers the given
/// declarations as "equivalent", e.g., if they are redeclarations of
/// the same entity or are both typedefs of the same type.
static bool
IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) {
  if (D1->getCanonicalDecl() == D2->getCanonicalDecl())
    return true;

  if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
    if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2))
      return Context.hasSameType(TD1->getUnderlyingType(),
                                 TD2->getUnderlyingType());

  return false;
}


/// Determines whether to create a using shadow decl for a particular
/// decl, given the set of decls existing prior to this using lookup.
bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
                                const LookupResult &Previous,
                                UsingShadowDecl *&PrevShadow) {
  // Diagnose finding a decl which is not from a base class of the
  // current class.  We do this now because there are cases where this
  // function will silently decide not to build a shadow decl, which
  // will pre-empt further diagnostics.
  //
  // We don't need to do this in C++11 because we do the check once on
  // the qualifier.
  //
  // FIXME: diagnose the following if we care enough:
  //   struct A { int foo; };
  //   struct B : A { using A::foo; };
  //   template <class T> struct C : A {};
  //   template <class T> struct D : C<T> { using B::foo; } // <---
  // This is invalid (during instantiation) in C++03 because B::foo
  // resolves to the using decl in B, which is not a base class of D<T>.
  // We can't diagnose it immediately because C<T> is an unknown
  // specialization.  The UsingShadowDecl in D<T> then points directly
  // to A::foo, which will look well-formed when we instantiate.
  // The right solution is to not collapse the shadow-decl chain.
  if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) {
    DeclContext *OrigDC = Orig->getDeclContext();

    // Handle enums and anonymous structs.
    if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
    CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
    while (OrigRec->isAnonymousStructOrUnion())
      OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());

    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
      if (OrigDC == CurContext) {
        Diag(Using->getLocation(),
             diag::err_using_decl_nested_name_specifier_is_current_class)
          << Using->getQualifierLoc().getSourceRange();
        Diag(Orig->getLocation(), diag::note_using_decl_target);
        Using->setInvalidDecl();
        return true;
      }

      Diag(Using->getQualifierLoc().getBeginLoc(),
           diag::err_using_decl_nested_name_specifier_is_not_base_class)
        << Using->getQualifier()
        << cast<CXXRecordDecl>(CurContext)
        << Using->getQualifierLoc().getSourceRange();
      Diag(Orig->getLocation(), diag::note_using_decl_target);
      Using->setInvalidDecl();
      return true;
    }
  }

  if (Previous.empty()) return false;

  NamedDecl *Target = Orig;
  if (isa<UsingShadowDecl>(Target))
    Target = cast<UsingShadowDecl>(Target)->getTargetDecl();

  // If the target happens to be one of the previous declarations, we
  // don't have a conflict.
  //
  // FIXME: but we might be increasing its access, in which case we
  // should redeclare it.
  NamedDecl *NonTag = nullptr, *Tag = nullptr;
  bool FoundEquivalentDecl = false;
  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
         I != E; ++I) {
    NamedDecl *D = (*I)->getUnderlyingDecl();
    // We can have UsingDecls in our Previous results because we use the same
    // LookupResult for checking whether the UsingDecl itself is a valid
    // redeclaration.
    if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D))
      continue;

    if (auto *RD = dyn_cast<CXXRecordDecl>(D)) {
      // C++ [class.mem]p19:
      //   If T is the name of a class, then [every named member other than
      //   a non-static data member] shall have a name different from T
      if (RD->isInjectedClassName() && !isa<FieldDecl>(Target) &&
          !isa<IndirectFieldDecl>(Target) &&
          !isa<UnresolvedUsingValueDecl>(Target) &&
          DiagnoseClassNameShadow(
              CurContext,
              DeclarationNameInfo(Using->getDeclName(), Using->getLocation())))
        return true;
    }

    if (IsEquivalentForUsingDecl(Context, D, Target)) {
      if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
        PrevShadow = Shadow;
      FoundEquivalentDecl = true;
    } else if (isEquivalentInternalLinkageDeclaration(D, Target)) {
      // We don't conflict with an existing using shadow decl of an equivalent
      // declaration, but we're not a redeclaration of it.
      FoundEquivalentDecl = true;
    }

    if (isVisible(D))
      (isa<TagDecl>(D) ? Tag : NonTag) = D;
  }

  if (FoundEquivalentDecl)
    return false;

  if (FunctionDecl *FD = Target->getAsFunction()) {
    NamedDecl *OldDecl = nullptr;
    switch (CheckOverload(nullptr, FD, Previous, OldDecl,
                          /*IsForUsingDecl*/ true)) {
    case Ovl_Overload:
      return false;

    case Ovl_NonFunction:
      Diag(Using->getLocation(), diag::err_using_decl_conflict);
      break;

    // We found a decl with the exact signature.
    case Ovl_Match:
      // If we're in a record, we want to hide the target, so we
      // return true (without a diagnostic) to tell the caller not to
      // build a shadow decl.
      if (CurContext->isRecord())
        return true;

      // If we're not in a record, this is an error.
      Diag(Using->getLocation(), diag::err_using_decl_conflict);
      break;
    }

    Diag(Target->getLocation(), diag::note_using_decl_target);
    Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
    Using->setInvalidDecl();
    return true;
  }

  // Target is not a function.

  if (isa<TagDecl>(Target)) {
    // No conflict between a tag and a non-tag.
    if (!Tag) return false;

    Diag(Using->getLocation(), diag::err_using_decl_conflict);
    Diag(Target->getLocation(), diag::note_using_decl_target);
    Diag(Tag->getLocation(), diag::note_using_decl_conflict);
    Using->setInvalidDecl();
    return true;
  }

  // No conflict between a tag and a non-tag.
  if (!NonTag) return false;

  Diag(Using->getLocation(), diag::err_using_decl_conflict);
  Diag(Target->getLocation(), diag::note_using_decl_target);
  Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
  Using->setInvalidDecl();
  return true;
}

/// Determine whether a direct base class is a virtual base class.
static bool isVirtualDirectBase(CXXRecordDecl *Derived, CXXRecordDecl *Base) {
  if (!Derived->getNumVBases())
    return false;
  for (auto &B : Derived->bases())
    if (B.getType()->getAsCXXRecordDecl() == Base)
      return B.isVirtual();
  llvm_unreachable("not a direct base class");
}

/// Builds a shadow declaration corresponding to a 'using' declaration.
UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
                                            UsingDecl *UD,
                                            NamedDecl *Orig,
                                            UsingShadowDecl *PrevDecl) {
  // If we resolved to another shadow declaration, just coalesce them.
  NamedDecl *Target = Orig;
  if (isa<UsingShadowDecl>(Target)) {
    Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
    assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
  }

  NamedDecl *NonTemplateTarget = Target;
  if (auto *TargetTD = dyn_cast<TemplateDecl>(Target))
    NonTemplateTarget = TargetTD->getTemplatedDecl();

  UsingShadowDecl *Shadow;
  if (isa<CXXConstructorDecl>(NonTemplateTarget)) {
    bool IsVirtualBase =
        isVirtualDirectBase(cast<CXXRecordDecl>(CurContext),
                            UD->getQualifier()->getAsRecordDecl());
    Shadow = ConstructorUsingShadowDecl::Create(
        Context, CurContext, UD->getLocation(), UD, Orig, IsVirtualBase);
  } else {
    Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD,
                                     Target);
  }
  UD->addShadowDecl(Shadow);

  Shadow->setAccess(UD->getAccess());
  if (Orig->isInvalidDecl() || UD->isInvalidDecl())
    Shadow->setInvalidDecl();

  Shadow->setPreviousDecl(PrevDecl);

  if (S)
    PushOnScopeChains(Shadow, S);
  else
    CurContext->addDecl(Shadow);


  return Shadow;
}

/// Hides a using shadow declaration.  This is required by the current
/// using-decl implementation when a resolvable using declaration in a
/// class is followed by a declaration which would hide or override
/// one or more of the using decl's targets; for example:
///
///   struct Base { void foo(int); };
///   struct Derived : Base {
///     using Base::foo;
///     void foo(int);
///   };
///
/// The governing language is C++03 [namespace.udecl]p12:
///
///   When a using-declaration brings names from a base class into a
///   derived class scope, member functions in the derived class
///   override and/or hide member functions with the same name and
///   parameter types in a base class (rather than conflicting).
///
/// There are two ways to implement this:
///   (1) optimistically create shadow decls when they're not hidden
///       by existing declarations, or
///   (2) don't create any shadow decls (or at least don't make them
///       visible) until we've fully parsed/instantiated the class.
/// The problem with (1) is that we might have to retroactively remove
/// a shadow decl, which requires several O(n) operations because the
/// decl structures are (very reasonably) not designed for removal.
/// (2) avoids this but is very fiddly and phase-dependent.
void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
  if (Shadow->getDeclName().getNameKind() ==
        DeclarationName::CXXConversionFunctionName)
    cast<CXXRecordDecl>(Shadow->getDeclContext())->removeConversion(Shadow);

  // Remove it from the DeclContext...
  Shadow->getDeclContext()->removeDecl(Shadow);

  // ...and the scope, if applicable...
  if (S) {
    S->RemoveDecl(Shadow);
    IdResolver.RemoveDecl(Shadow);
  }

  // ...and the using decl.
  Shadow->getUsingDecl()->removeShadowDecl(Shadow);

  // TODO: complain somehow if Shadow was used.  It shouldn't
  // be possible for this to happen, because...?
}

/// Find the base specifier for a base class with the given type.
static CXXBaseSpecifier *findDirectBaseWithType(CXXRecordDecl *Derived,
                                                QualType DesiredBase,
                                                bool &AnyDependentBases) {
  // Check whether the named type is a direct base class.
  CanQualType CanonicalDesiredBase = DesiredBase->getCanonicalTypeUnqualified();
  for (auto &Base : Derived->bases()) {
    CanQualType BaseType = Base.getType()->getCanonicalTypeUnqualified();
    if (CanonicalDesiredBase == BaseType)
      return &Base;
    if (BaseType->isDependentType())
      AnyDependentBases = true;
  }
  return nullptr;
}

namespace {
class UsingValidatorCCC final : public CorrectionCandidateCallback {
public:
  UsingValidatorCCC(bool HasTypenameKeyword, bool IsInstantiation,
                    NestedNameSpecifier *NNS, CXXRecordDecl *RequireMemberOf)
      : HasTypenameKeyword(HasTypenameKeyword),
        IsInstantiation(IsInstantiation), OldNNS(NNS),
        RequireMemberOf(RequireMemberOf) {}

  bool ValidateCandidate(const TypoCorrection &Candidate) override {
    NamedDecl *ND = Candidate.getCorrectionDecl();

    // Keywords are not valid here.
    if (!ND || isa<NamespaceDecl>(ND))
      return false;

    // Completely unqualified names are invalid for a 'using' declaration.
    if (Candidate.WillReplaceSpecifier() && !Candidate.getCorrectionSpecifier())
      return false;

    // FIXME: Don't correct to a name that CheckUsingDeclRedeclaration would
    // reject.

    if (RequireMemberOf) {
      auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND);
      if (FoundRecord && FoundRecord->isInjectedClassName()) {
        // No-one ever wants a using-declaration to name an injected-class-name
        // of a base class, unless they're declaring an inheriting constructor.
        ASTContext &Ctx = ND->getASTContext();
        if (!Ctx.getLangOpts().CPlusPlus11)
          return false;
        QualType FoundType = Ctx.getRecordType(FoundRecord);

        // Check that the injected-class-name is named as a member of its own
        // type; we don't want to suggest 'using Derived::Base;', since that
        // means something else.
        NestedNameSpecifier *Specifier =
            Candidate.WillReplaceSpecifier()
                ? Candidate.getCorrectionSpecifier()
                : OldNNS;
        if (!Specifier->getAsType() ||
            !Ctx.hasSameType(QualType(Specifier->getAsType(), 0), FoundType))
          return false;

        // Check that this inheriting constructor declaration actually names a
        // direct base class of the current class.
        bool AnyDependentBases = false;
        if (!findDirectBaseWithType(RequireMemberOf,
                                    Ctx.getRecordType(FoundRecord),
                                    AnyDependentBases) &&
            !AnyDependentBases)
          return false;
      } else {
        auto *RD = dyn_cast<CXXRecordDecl>(ND->getDeclContext());
        if (!RD || RequireMemberOf->isProvablyNotDerivedFrom(RD))
          return false;

        // FIXME: Check that the base class member is accessible?
      }
    } else {
      auto *FoundRecord = dyn_cast<CXXRecordDecl>(ND);
      if (FoundRecord && FoundRecord->isInjectedClassName())
        return false;
    }

    if (isa<TypeDecl>(ND))
      return HasTypenameKeyword || !IsInstantiation;

    return !HasTypenameKeyword;
  }

  std::unique_ptr<CorrectionCandidateCallback> clone() override {
    return llvm::make_unique<UsingValidatorCCC>(*this);
  }

private:
  bool HasTypenameKeyword;
  bool IsInstantiation;
  NestedNameSpecifier *OldNNS;
  CXXRecordDecl *RequireMemberOf;
};
} // end anonymous namespace

/// Builds a using declaration.
///
/// \param IsInstantiation - Whether this call arises from an
///   instantiation of an unresolved using declaration.  We treat
///   the lookup differently for these declarations.
NamedDecl *Sema::BuildUsingDeclaration(
    Scope *S, AccessSpecifier AS, SourceLocation UsingLoc,
    bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS,
    DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc,
    const ParsedAttributesView &AttrList, bool IsInstantiation) {
  assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
  SourceLocation IdentLoc = NameInfo.getLoc();
  assert(IdentLoc.isValid() && "Invalid TargetName location.");

  // FIXME: We ignore attributes for now.

  // For an inheriting constructor declaration, the name of the using
  // declaration is the name of a constructor in this class, not in the
  // base class.
  DeclarationNameInfo UsingName = NameInfo;
  if (UsingName.getName().getNameKind() == DeclarationName::CXXConstructorName)
    if (auto *RD = dyn_cast<CXXRecordDecl>(CurContext))
      UsingName.setName(Context.DeclarationNames.getCXXConstructorName(
          Context.getCanonicalType(Context.getRecordType(RD))));

  // Do the redeclaration lookup in the current scope.
  LookupResult Previous(*this, UsingName, LookupUsingDeclName,
                        ForVisibleRedeclaration);
  Previous.setHideTags(false);
  if (S) {
    LookupName(Previous, S);

    // It is really dumb that we have to do this.
    LookupResult::Filter F = Previous.makeFilter();
    while (F.hasNext()) {
      NamedDecl *D = F.next();
      if (!isDeclInScope(D, CurContext, S))
        F.erase();
      // If we found a local extern declaration that's not ordinarily visible,
      // and this declaration is being added to a non-block scope, ignore it.
      // We're only checking for scope conflicts here, not also for violations
      // of the linkage rules.
      else if (!CurContext->isFunctionOrMethod() && D->isLocalExternDecl() &&
               !(D->getIdentifierNamespace() & Decl::IDNS_Ordinary))
        F.erase();
    }
    F.done();
  } else {
    assert(IsInstantiation && "no scope in non-instantiation");
    if (CurContext->isRecord())
      LookupQualifiedName(Previous, CurContext);
    else {
      // No redeclaration check is needed here; in non-member contexts we
      // diagnosed all possible conflicts with other using-declarations when
      // building the template:
      //
      // For a dependent non-type using declaration, the only valid case is
      // if we instantiate to a single enumerator. We check for conflicts
      // between shadow declarations we introduce, and we check in the template
      // definition for conflicts between a non-type using declaration and any
      // other declaration, which together covers all cases.
      //
      // A dependent typename using declaration will never successfully
      // instantiate, since it will always name a class member, so we reject
      // that in the template definition.
    }
  }

  // Check for invalid redeclarations.
  if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword,
                                  SS, IdentLoc, Previous))
    return nullptr;

  // Check for bad qualifiers.
  if (CheckUsingDeclQualifier(UsingLoc, HasTypenameKeyword, SS, NameInfo,
                              IdentLoc))
    return nullptr;

  DeclContext *LookupContext = computeDeclContext(SS);
  NamedDecl *D;
  NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
  if (!LookupContext || EllipsisLoc.isValid()) {
    if (HasTypenameKeyword) {
      // FIXME: not all declaration name kinds are legal here
      D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
                                              UsingLoc, TypenameLoc,
                                              QualifierLoc,
                                              IdentLoc, NameInfo.getName(),
                                              EllipsisLoc);
    } else {
      D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc,
                                           QualifierLoc, NameInfo, EllipsisLoc);
    }
    D->setAccess(AS);
    CurContext->addDecl(D);
    return D;
  }

  auto Build = [&](bool Invalid) {
    UsingDecl *UD =
        UsingDecl::Create(Context, CurContext, UsingLoc, QualifierLoc,
                          UsingName, HasTypenameKeyword);
    UD->setAccess(AS);
    CurContext->addDecl(UD);
    UD->setInvalidDecl(Invalid);
    return UD;
  };
  auto BuildInvalid = [&]{ return Build(true); };
  auto BuildValid = [&]{ return Build(false); };

  if (RequireCompleteDeclContext(SS, LookupContext))
    return BuildInvalid();

  // Look up the target name.
  LookupResult R(*this, NameInfo, LookupOrdinaryName);

  // Unlike most lookups, we don't always want to hide tag
  // declarations: tag names are visible through the using declaration
  // even if hidden by ordinary names, *except* in a dependent context
  // where it's important for the sanity of two-phase lookup.
  if (!IsInstantiation)
    R.setHideTags(false);

  // For the purposes of this lookup, we have a base object type
  // equal to that of the current context.
  if (CurContext->isRecord()) {
    R.setBaseObjectType(
                   Context.getTypeDeclType(cast<CXXRecordDecl>(CurContext)));
  }

  LookupQualifiedName(R, LookupContext);

  // Try to correct typos if possible. If constructor name lookup finds no
  // results, that means the named class has no explicit constructors, and we
  // suppressed declaring implicit ones (probably because it's dependent or
  // invalid).
  if (R.empty() &&
      NameInfo.getName().getNameKind() != DeclarationName::CXXConstructorName) {
    // HACK: Work around a bug in libstdc++'s detection of ::gets. Sometimes
    // it will believe that glibc provides a ::gets in cases where it does not,
    // and will try to pull it into namespace std with a using-declaration.
    // Just ignore the using-declaration in that case.
    auto *II = NameInfo.getName().getAsIdentifierInfo();
    if (getLangOpts().CPlusPlus14 && II && II->isStr("gets") &&
        CurContext->isStdNamespace() &&
        isa<TranslationUnitDecl>(LookupContext) &&
        getSourceManager().isInSystemHeader(UsingLoc))
      return nullptr;
    UsingValidatorCCC CCC(HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
                          dyn_cast<CXXRecordDecl>(CurContext));
    if (TypoCorrection Corrected =
            CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, CCC,
                        CTK_ErrorRecovery)) {
      // We reject candidates where DroppedSpecifier == true, hence the
      // literal '0' below.
      diagnoseTypo(Corrected, PDiag(diag::err_no_member_suggest)
                                << NameInfo.getName() << LookupContext << 0
                                << SS.getRange());

      // If we picked a correction with no attached Decl we can't do anything
      // useful with it, bail out.
      NamedDecl *ND = Corrected.getCorrectionDecl();
      if (!ND)
        return BuildInvalid();

      // If we corrected to an inheriting constructor, handle it as one.
      auto *RD = dyn_cast<CXXRecordDecl>(ND);
      if (RD && RD->isInjectedClassName()) {
        // The parent of the injected class name is the class itself.
        RD = cast<CXXRecordDecl>(RD->getParent());

        // Fix up the information we'll use to build the using declaration.
        if (Corrected.WillReplaceSpecifier()) {
          NestedNameSpecifierLocBuilder Builder;
          Builder.MakeTrivial(Context, Corrected.getCorrectionSpecifier(),
                              QualifierLoc.getSourceRange());
          QualifierLoc = Builder.getWithLocInContext(Context);
        }

        // In this case, the name we introduce is the name of a derived class
        // constructor.
        auto *CurClass = cast<CXXRecordDecl>(CurContext);
        UsingName.setName(Context.DeclarationNames.getCXXConstructorName(
            Context.getCanonicalType(Context.getRecordType(CurClass))));
        UsingName.setNamedTypeInfo(nullptr);
        for (auto *Ctor : LookupConstructors(RD))
          R.addDecl(Ctor);
        R.resolveKind();
      } else {
        // FIXME: Pick up all the declarations if we found an overloaded
        // function.
        UsingName.setName(ND->getDeclName());
        R.addDecl(ND);
      }
    } else {
      Diag(IdentLoc, diag::err_no_member)
        << NameInfo.getName() << LookupContext << SS.getRange();
      return BuildInvalid();
    }
  }

  if (R.isAmbiguous())
    return BuildInvalid();

  if (HasTypenameKeyword) {
    // If we asked for a typename and got a non-type decl, error out.
    if (!R.getAsSingle<TypeDecl>()) {
      Diag(IdentLoc, diag::err_using_typename_non_type);
      for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
        Diag((*I)->getUnderlyingDecl()->getLocation(),
             diag::note_using_decl_target);
      return BuildInvalid();
    }
  } else {
    // If we asked for a non-typename and we got a type, error out,
    // but only if this is an instantiation of an unresolved using
    // decl.  Otherwise just silently find the type name.
    if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
      Diag(IdentLoc, diag::err_using_dependent_value_is_type);
      Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
      return BuildInvalid();
    }
  }

  // C++14 [namespace.udecl]p6:
  // A using-declaration shall not name a namespace.
  if (R.getAsSingle<NamespaceDecl>()) {
    Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
      << SS.getRange();
    return BuildInvalid();
  }

  // C++14 [namespace.udecl]p7:
  // A using-declaration shall not name a scoped enumerator.
  if (auto *ED = R.getAsSingle<EnumConstantDecl>()) {
    if (cast<EnumDecl>(ED->getDeclContext())->isScoped()) {
      Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_scoped_enum)
        << SS.getRange();
      return BuildInvalid();
    }
  }

  UsingDecl *UD = BuildValid();

  // Some additional rules apply to inheriting constructors.
  if (UsingName.getName().getNameKind() ==
        DeclarationName::CXXConstructorName) {
    // Suppress access diagnostics; the access check is instead performed at the
    // point of use for an inheriting constructor.
    R.suppressDiagnostics();
    if (CheckInheritingConstructorUsingDecl(UD))
      return UD;
  }

  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
    UsingShadowDecl *PrevDecl = nullptr;
    if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
      BuildUsingShadowDecl(S, UD, *I, PrevDecl);
  }

  return UD;
}

NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom,
                                    ArrayRef<NamedDecl *> Expansions) {
  assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) ||
         isa<UnresolvedUsingTypenameDecl>(InstantiatedFrom) ||
         isa<UsingPackDecl>(InstantiatedFrom));

  auto *UPD =
      UsingPackDecl::Create(Context, CurContext, InstantiatedFrom, Expansions);
  UPD->setAccess(InstantiatedFrom->getAccess());
  CurContext->addDecl(UPD);
  return UPD;
}

/// Additional checks for a using declaration referring to a constructor name.
bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) {
  assert(!UD->hasTypename() && "expecting a constructor name");

  const Type *SourceType = UD->getQualifier()->getAsType();
  assert(SourceType &&
         "Using decl naming constructor doesn't have type in scope spec.");
  CXXRecordDecl *TargetClass = cast<CXXRecordDecl>(CurContext);

  // Check whether the named type is a direct base class.
  bool AnyDependentBases = false;
  auto *Base = findDirectBaseWithType(TargetClass, QualType(SourceType, 0),
                                      AnyDependentBases);
  if (!Base && !AnyDependentBases) {
    Diag(UD->getUsingLoc(),
         diag::err_using_decl_constructor_not_in_direct_base)
      << UD->getNameInfo().getSourceRange()
      << QualType(SourceType, 0) << TargetClass;
    UD->setInvalidDecl();
    return true;
  }

  if (Base)
    Base->setInheritConstructors();

  return false;
}

/// Checks that the given using declaration is not an invalid
/// redeclaration.  Note that this is checking only for the using decl
/// itself, not for any ill-formedness among the UsingShadowDecls.
bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
                                       bool HasTypenameKeyword,
                                       const CXXScopeSpec &SS,
                                       SourceLocation NameLoc,
                                       const LookupResult &Prev) {
  NestedNameSpecifier *Qual = SS.getScopeRep();

  // C++03 [namespace.udecl]p8:
  // C++0x [namespace.udecl]p10:
  //   A using-declaration is a declaration and can therefore be used
  //   repeatedly where (and only where) multiple declarations are
  //   allowed.
  //
  // That's in non-member contexts.
  if (!CurContext->getRedeclContext()->isRecord()) {
    // A dependent qualifier outside a class can only ever resolve to an
    // enumeration type. Therefore it conflicts with any other non-type
    // declaration in the same scope.
    // FIXME: How should we check for dependent type-type conflicts at block
    // scope?
    if (Qual->isDependent() && !HasTypenameKeyword) {
      for (auto *D : Prev) {
        if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) {
          bool OldCouldBeEnumerator =
              isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D);
          Diag(NameLoc,
               OldCouldBeEnumerator ? diag::err_redefinition
                                    : diag::err_redefinition_different_kind)
              << Prev.getLookupName();
          Diag(D->getLocation(), diag::note_previous_definition);
          return true;
        }
      }
    }
    return false;
  }

  for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
    NamedDecl *D = *I;

    bool DTypename;
    NestedNameSpecifier *DQual;
    if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
      DTypename = UD->hasTypename();
      DQual = UD->getQualifier();
    } else if (UnresolvedUsingValueDecl *UD
                 = dyn_cast<UnresolvedUsingValueDecl>(D)) {
      DTypename = false;
      DQual = UD->getQualifier();
    } else if (UnresolvedUsingTypenameDecl *UD
                 = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
      DTypename = true;
      DQual = UD->getQualifier();
    } else continue;

    // using decls differ if one says 'typename' and the other doesn't.
    // FIXME: non-dependent using decls?
    if (HasTypenameKeyword != DTypename) continue;

    // using decls differ if they name different scopes (but note that
    // template instantiation can cause this check to trigger when it
    // didn't before instantiation).
    if (Context.getCanonicalNestedNameSpecifier(Qual) !=
        Context.getCanonicalNestedNameSpecifier(DQual))
      continue;

    Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
    Diag(D->getLocation(), diag::note_using_decl) << 1;
    return true;
  }

  return false;
}


/// Checks that the given nested-name qualifier used in a using decl
/// in the current context is appropriately related to the current
/// scope.  If an error is found, diagnoses it and returns true.
bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
                                   bool HasTypename,
                                   const CXXScopeSpec &SS,
                                   const DeclarationNameInfo &NameInfo,
                                   SourceLocation NameLoc) {
  DeclContext *NamedContext = computeDeclContext(SS);

  if (!CurContext->isRecord()) {
    // C++03 [namespace.udecl]p3:
    // C++0x [namespace.udecl]p8:
    //   A using-declaration for a class member shall be a member-declaration.

    // If we weren't able to compute a valid scope, it might validly be a
    // dependent class scope or a dependent enumeration unscoped scope. If
    // we have a 'typename' keyword, the scope must resolve to a class type.
    if ((HasTypename && !NamedContext) ||
        (NamedContext && NamedContext->getRedeclContext()->isRecord())) {
      auto *RD = NamedContext
                     ? cast<CXXRecordDecl>(NamedContext->getRedeclContext())
                     : nullptr;
      if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), RD))
        RD = nullptr;

      Diag(NameLoc, diag::err_using_decl_can_not_refer_to_class_member)
        << SS.getRange();

      // If we have a complete, non-dependent source type, try to suggest a
      // way to get the same effect.
      if (!RD)
        return true;

      // Find what this using-declaration was referring to.
      LookupResult R(*this, NameInfo, LookupOrdinaryName);
      R.setHideTags(false);
      R.suppressDiagnostics();
      LookupQualifiedName(R, RD);

      if (R.getAsSingle<TypeDecl>()) {
        if (getLangOpts().CPlusPlus11) {
          // Convert 'using X::Y;' to 'using Y = X::Y;'.
          Diag(SS.getBeginLoc(), diag::note_using_decl_class_member_workaround)
            << 0 // alias declaration
            << FixItHint::CreateInsertion(SS.getBeginLoc(),
                                          NameInfo.getName().getAsString() +
                                              " = ");
        } else {
          // Convert 'using X::Y;' to 'typedef X::Y Y;'.
          SourceLocation InsertLoc = getLocForEndOfToken(NameInfo.getEndLoc());
          Diag(InsertLoc, diag::note_using_decl_class_member_workaround)
            << 1 // typedef declaration
            << FixItHint::CreateReplacement(UsingLoc, "typedef")
            << FixItHint::CreateInsertion(
                   InsertLoc, " " + NameInfo.getName().getAsString());
        }
      } else if (R.getAsSingle<VarDecl>()) {
        // Don't provide a fixit outside C++11 mode; we don't want to suggest
        // repeating the type of the static data member here.
        FixItHint FixIt;
        if (getLangOpts().CPlusPlus11) {
          // Convert 'using X::Y;' to 'auto &Y = X::Y;'.
          FixIt = FixItHint::CreateReplacement(
              UsingLoc, "auto &" + NameInfo.getName().getAsString() + " = ");
        }

        Diag(UsingLoc, diag::note_using_decl_class_member_workaround)
          << 2 // reference declaration
          << FixIt;
      } else if (R.getAsSingle<EnumConstantDecl>()) {
        // Don't provide a fixit outside C++11 mode; we don't want to suggest
        // repeating the type of the enumeration here, and we can't do so if
        // the type is anonymous.
        FixItHint FixIt;
        if (getLangOpts().CPlusPlus11) {
          // Convert 'using X::Y;' to 'auto &Y = X::Y;'.
          FixIt = FixItHint::CreateReplacement(
              UsingLoc,
              "constexpr auto " + NameInfo.getName().getAsString() + " = ");
        }

        Diag(UsingLoc, diag::note_using_decl_class_member_workaround)
          << (getLangOpts().CPlusPlus11 ? 4 : 3) // const[expr] variable
          << FixIt;
      }
      return true;
    }

    // Otherwise, this might be valid.
    return false;
  }

  // The current scope is a record.

  // If the named context is dependent, we can't decide much.
  if (!NamedContext) {
    // FIXME: in C++0x, we can diagnose if we can prove that the
    // nested-name-specifier does not refer to a base class, which is
    // still possible in some cases.

    // Otherwise we have to conservatively report that things might be
    // okay.
    return false;
  }

  if (!NamedContext->isRecord()) {
    // Ideally this would point at the last name in the specifier,
    // but we don't have that level of source info.
    Diag(SS.getRange().getBegin(),
         diag::err_using_decl_nested_name_specifier_is_not_class)
      << SS.getScopeRep() << SS.getRange();
    return true;
  }

  if (!NamedContext->isDependentContext() &&
      RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS), NamedContext))
    return true;

  if (getLangOpts().CPlusPlus11) {
    // C++11 [namespace.udecl]p3:
    //   In a using-declaration used as a member-declaration, the
    //   nested-name-specifier shall name a base class of the class
    //   being defined.

    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(
                                 cast<CXXRecordDecl>(NamedContext))) {
      if (CurContext == NamedContext) {
        Diag(NameLoc,
             diag::err_using_decl_nested_name_specifier_is_current_class)
          << SS.getRange();
        return true;
      }

      if (!cast<CXXRecordDecl>(NamedContext)->isInvalidDecl()) {
        Diag(SS.getRange().getBegin(),
             diag::err_using_decl_nested_name_specifier_is_not_base_class)
          << SS.getScopeRep()
          << cast<CXXRecordDecl>(CurContext)
          << SS.getRange();
      }
      return true;
    }

    return false;
  }

  // C++03 [namespace.udecl]p4:
  //   A using-declaration used as a member-declaration shall refer
  //   to a member of a base class of the class being defined [etc.].

  // Salient point: SS doesn't have to name a base class as long as
  // lookup only finds members from base classes.  Therefore we can
  // diagnose here only if we can prove that that can't happen,
  // i.e. if the class hierarchies provably don't intersect.

  // TODO: it would be nice if "definitely valid" results were cached
  // in the UsingDecl and UsingShadowDecl so that these checks didn't
  // need to be repeated.

  llvm::SmallPtrSet<const CXXRecordDecl *, 4> Bases;
  auto Collect = [&Bases](const CXXRecordDecl *Base) {
    Bases.insert(Base);
    return true;
  };

  // Collect all bases. Return false if we find a dependent base.
  if (!cast<CXXRecordDecl>(CurContext)->forallBases(Collect))
    return false;

  // Returns true if the base is dependent or is one of the accumulated base
  // classes.
  auto IsNotBase = [&Bases](const CXXRecordDecl *Base) {
    return !Bases.count(Base);
  };

  // Return false if the class has a dependent base or if it or one
  // of its bases is present in the base set of the current context.
  if (Bases.count(cast<CXXRecordDecl>(NamedContext)) ||
      !cast<CXXRecordDecl>(NamedContext)->forallBases(IsNotBase))
    return false;

  Diag(SS.getRange().getBegin(),
       diag::err_using_decl_nested_name_specifier_is_not_base_class)
    << SS.getScopeRep()
    << cast<CXXRecordDecl>(CurContext)
    << SS.getRange();

  return true;
}

Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
                                  MultiTemplateParamsArg TemplateParamLists,
                                  SourceLocation UsingLoc, UnqualifiedId &Name,
                                  const ParsedAttributesView &AttrList,
                                  TypeResult Type, Decl *DeclFromDeclSpec) {
  // Skip up to the relevant declaration scope.
  while (S->isTemplateParamScope())
    S = S->getParent();
  assert((S->getFlags() & Scope::DeclScope) &&
         "got alias-declaration outside of declaration scope");

  if (Type.isInvalid())
    return nullptr;

  bool Invalid = false;
  DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name);
  TypeSourceInfo *TInfo = nullptr;
  GetTypeFromParser(Type.get(), &TInfo);

  if (DiagnoseClassNameShadow(CurContext, NameInfo))
    return nullptr;

  if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo,
                                      UPPC_DeclarationType)) {
    Invalid = true;
    TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
                                             TInfo->getTypeLoc().getBeginLoc());
  }

  LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
                        TemplateParamLists.size()
                            ? forRedeclarationInCurContext()
                            : ForVisibleRedeclaration);
  LookupName(Previous, S);

  // Warn about shadowing the name of a template parameter.
  if (Previous.isSingleResult() &&
      Previous.getFoundDecl()->isTemplateParameter()) {
    DiagnoseTemplateParameterShadow(Name.StartLocation,Previous.getFoundDecl());
    Previous.clear();
  }

  assert(Name.Kind == UnqualifiedIdKind::IK_Identifier &&
         "name in alias declaration must be an identifier");
  TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc,
                                               Name.StartLocation,
                                               Name.Identifier, TInfo);

  NewTD->setAccess(AS);

  if (Invalid)
    NewTD->setInvalidDecl();

  ProcessDeclAttributeList(S, NewTD, AttrList);
  AddPragmaAttributes(S, NewTD);

  CheckTypedefForVariablyModifiedType(S, NewTD);
  Invalid |= NewTD->isInvalidDecl();

  bool Redeclaration = false;

  NamedDecl *NewND;
  if (TemplateParamLists.size()) {
    TypeAliasTemplateDecl *OldDecl = nullptr;
    TemplateParameterList *OldTemplateParams = nullptr;

    if (TemplateParamLists.size() != 1) {
      Diag(UsingLoc, diag::err_alias_template_extra_headers)
        << SourceRange(TemplateParamLists[1]->getTemplateLoc(),
         TemplateParamLists[TemplateParamLists.size()-1]->getRAngleLoc());
    }
    TemplateParameterList *TemplateParams = TemplateParamLists[0];

    // Check that we can declare a template here.
    if (CheckTemplateDeclScope(S, TemplateParams))
      return nullptr;

    // Only consider previous declarations in the same scope.
    FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage*/false,
                         /*ExplicitInstantiationOrSpecialization*/false);
    if (!Previous.empty()) {
      Redeclaration = true;

      OldDecl = Previous.getAsSingle<TypeAliasTemplateDecl>();
      if (!OldDecl && !Invalid) {
        Diag(UsingLoc, diag::err_redefinition_different_kind)
          << Name.Identifier;

        NamedDecl *OldD = Previous.getRepresentativeDecl();
        if (OldD->getLocation().isValid())
          Diag(OldD->getLocation(), diag::note_previous_definition);

        Invalid = true;
      }

      if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) {
        if (TemplateParameterListsAreEqual(TemplateParams,
                                           OldDecl->getTemplateParameters(),
                                           /*Complain=*/true,
                                           TPL_TemplateMatch))
          OldTemplateParams =
              OldDecl->getMostRecentDecl()->getTemplateParameters();
        else
          Invalid = true;

        TypeAliasDecl *OldTD = OldDecl->getTemplatedDecl();
        if (!Invalid &&
            !Context.hasSameType(OldTD->getUnderlyingType(),
                                 NewTD->getUnderlyingType())) {
          // FIXME: The C++0x standard does not clearly say this is ill-formed,
          // but we can't reasonably accept it.
          Diag(NewTD->getLocation(), diag::err_redefinition_different_typedef)
            << 2 << NewTD->getUnderlyingType() << OldTD->getUnderlyingType();
          if (OldTD->getLocation().isValid())
            Diag(OldTD->getLocation(), diag::note_previous_definition);
          Invalid = true;
        }
      }
    }

    // Merge any previous default template arguments into our parameters,
    // and check the parameter list.
    if (CheckTemplateParameterList(TemplateParams, OldTemplateParams,
                                   TPC_TypeAliasTemplate))
      return nullptr;

    TypeAliasTemplateDecl *NewDecl =
      TypeAliasTemplateDecl::Create(Context, CurContext, UsingLoc,
                                    Name.Identifier, TemplateParams,
                                    NewTD);
    NewTD->setDescribedAliasTemplate(NewDecl);

    NewDecl->setAccess(AS);

    if (Invalid)
      NewDecl->setInvalidDecl();
    else if (OldDecl) {
      NewDecl->setPreviousDecl(OldDecl);
      CheckRedeclarationModuleOwnership(NewDecl, OldDecl);
    }

    NewND = NewDecl;
  } else {
    if (auto *TD = dyn_cast_or_null<TagDecl>(DeclFromDeclSpec)) {
      setTagNameForLinkagePurposes(TD, NewTD);
      handleTagNumbering(TD, S);
    }
    ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration);
    NewND = NewTD;
  }

  PushOnScopeChains(NewND, S);
  ActOnDocumentableDecl(NewND);
  return NewND;
}

Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,
                                   SourceLocation AliasLoc,
                                   IdentifierInfo *Alias, CXXScopeSpec &SS,
                                   SourceLocation IdentLoc,
                                   IdentifierInfo *Ident) {

  // Lookup the namespace name.
  LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
  LookupParsedName(R, S, &SS);

  if (R.isAmbiguous())
    return nullptr;

  if (R.empty()) {
    if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {
      Diag(IdentLoc, diag::err_expected_namespace_name) << SS.getRange();
      return nullptr;
    }
  }
  assert(!R.isAmbiguous() && !R.empty());
  NamedDecl *ND = R.getRepresentativeDecl();

  // Check if we have a previous declaration with the same name.
  LookupResult PrevR(*this, Alias, AliasLoc, LookupOrdinaryName,
                     ForVisibleRedeclaration);
  LookupName(PrevR, S);

  // Check we're not shadowing a template parameter.
  if (PrevR.isSingleResult() && PrevR.getFoundDecl()->isTemplateParameter()) {
    DiagnoseTemplateParameterShadow(AliasLoc, PrevR.getFoundDecl());
    PrevR.clear();
  }

  // Filter out any other lookup result from an enclosing scope.
  FilterLookupForScope(PrevR, CurContext, S, /*ConsiderLinkage*/false,
                       /*AllowInlineNamespace*/false);

  // Find the previous declaration and check that we can redeclare it.
  NamespaceAliasDecl *Prev = nullptr;
  if (PrevR.isSingleResult()) {
    NamedDecl *PrevDecl = PrevR.getRepresentativeDecl();
    if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(PrevDecl)) {
      // We already have an alias with the same name that points to the same
      // namespace; check that it matches.
      if (AD->getNamespace()->Equals(getNamespaceDecl(ND))) {
        Prev = AD;
      } else if (isVisible(PrevDecl)) {
        Diag(AliasLoc, diag::err_redefinition_different_namespace_alias)
          << Alias;
        Diag(AD->getLocation(), diag::note_previous_namespace_alias)
          << AD->getNamespace();
        return nullptr;
      }
    } else if (isVisible(PrevDecl)) {
      unsigned DiagID = isa<NamespaceDecl>(PrevDecl->getUnderlyingDecl())
                            ? diag::err_redefinition
                            : diag::err_redefinition_different_kind;
      Diag(AliasLoc, DiagID) << Alias;
      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
      return nullptr;
    }
  }

  // The use of a nested name specifier may trigger deprecation warnings.
  DiagnoseUseOfDecl(ND, IdentLoc);

  NamespaceAliasDecl *AliasDecl =
    NamespaceAliasDecl::Create(Context, CurContext, NamespaceLoc, AliasLoc,
                               Alias, SS.getWithLocInContext(Context),
                               IdentLoc, ND);
  if (Prev)
    AliasDecl->setPreviousDecl(Prev);

  PushOnScopeChains(AliasDecl, S);
  return AliasDecl;
}

namespace {
struct SpecialMemberExceptionSpecInfo
    : SpecialMemberVisitor<SpecialMemberExceptionSpecInfo> {
  SourceLocation Loc;
  Sema::ImplicitExceptionSpecification ExceptSpec;

  SpecialMemberExceptionSpecInfo(Sema &S, CXXMethodDecl *MD,
                                 Sema::CXXSpecialMember CSM,
                                 Sema::InheritedConstructorInfo *ICI,
                                 SourceLocation Loc)
      : SpecialMemberVisitor(S, MD, CSM, ICI), Loc(Loc), ExceptSpec(S) {}

  bool visitBase(CXXBaseSpecifier *Base);
  bool visitField(FieldDecl *FD);

  void visitClassSubobject(CXXRecordDecl *Class, Subobject Subobj,
                           unsigned Quals);

  void visitSubobjectCall(Subobject Subobj,
                          Sema::SpecialMemberOverloadResult SMOR);
};
}

bool SpecialMemberExceptionSpecInfo::visitBase(CXXBaseSpecifier *Base) {
  auto *RT = Base->getType()->getAs<RecordType>();
  if (!RT)
    return false;

  auto *BaseClass = cast<CXXRecordDecl>(RT->getDecl());
  Sema::SpecialMemberOverloadResult SMOR = lookupInheritedCtor(BaseClass);
  if (auto *BaseCtor = SMOR.getMethod()) {
    visitSubobjectCall(Base, BaseCtor);
    return false;
  }

  visitClassSubobject(BaseClass, Base, 0);
  return false;
}

bool SpecialMemberExceptionSpecInfo::visitField(FieldDecl *FD) {
  if (CSM == Sema::CXXDefaultConstructor && FD->hasInClassInitializer()) {
    Expr *E = FD->getInClassInitializer();
    if (!E)
      // FIXME: It's a little wasteful to build and throw away a
      // CXXDefaultInitExpr here.
      // FIXME: We should have a single context note pointing at Loc, and
      // this location should be MD->getLocation() instead, since that's
      // the location where we actually use the default init expression.
      E = S.BuildCXXDefaultInitExpr(Loc, FD).get();
    if (E)
      ExceptSpec.CalledExpr(E);
  } else if (auto *RT = S.Context.getBaseElementType(FD->getType())
                            ->getAs<RecordType>()) {
    visitClassSubobject(cast<CXXRecordDecl>(RT->getDecl()), FD,
                        FD->getType().getCVRQualifiers());
  }
  return false;
}

void SpecialMemberExceptionSpecInfo::visitClassSubobject(CXXRecordDecl *Class,
                                                         Subobject Subobj,
                                                         unsigned Quals) {
  FieldDecl *Field = Subobj.dyn_cast<FieldDecl*>();
  bool IsMutable = Field && Field->isMutable();
  visitSubobjectCall(Subobj, lookupIn(Class, Quals, IsMutable));
}

void SpecialMemberExceptionSpecInfo::visitSubobjectCall(
    Subobject Subobj, Sema::SpecialMemberOverloadResult SMOR) {
  // Note, if lookup fails, it doesn't matter what exception specification we
  // choose because the special member will be deleted.
  if (CXXMethodDecl *MD = SMOR.getMethod())
    ExceptSpec.CalledDecl(getSubobjectLoc(Subobj), MD);
}

namespace {
/// RAII object to register a special member as being currently declared.
struct ComputingExceptionSpec {
  Sema &S;

  ComputingExceptionSpec(Sema &S, CXXMethodDecl *MD, SourceLocation Loc)
      : S(S) {
    Sema::CodeSynthesisContext Ctx;
    Ctx.Kind = Sema::CodeSynthesisContext::ExceptionSpecEvaluation;
    Ctx.PointOfInstantiation = Loc;
    Ctx.Entity = MD;
    S.pushCodeSynthesisContext(Ctx);
  }
  ~ComputingExceptionSpec() {
    S.popCodeSynthesisContext();
  }
};
}

bool Sema::tryResolveExplicitSpecifier(ExplicitSpecifier &ExplicitSpec) {
  llvm::APSInt Result;
  ExprResult Converted = CheckConvertedConstantExpression(
      ExplicitSpec.getExpr(), Context.BoolTy, Result, CCEK_ExplicitBool);
  ExplicitSpec.setExpr(Converted.get());
  if (Converted.isUsable() && !Converted.get()->isValueDependent()) {
    ExplicitSpec.setKind(Result.getBoolValue()
                             ? ExplicitSpecKind::ResolvedTrue
                             : ExplicitSpecKind::ResolvedFalse);
    return true;
  }
  ExplicitSpec.setKind(ExplicitSpecKind::Unresolved);
  return false;
}

ExplicitSpecifier Sema::ActOnExplicitBoolSpecifier(Expr *ExplicitExpr) {
  ExplicitSpecifier ES(ExplicitExpr, ExplicitSpecKind::Unresolved);
  if (!ExplicitExpr->isTypeDependent())
    tryResolveExplicitSpecifier(ES);
  return ES;
}

static Sema::ImplicitExceptionSpecification
ComputeDefaultedSpecialMemberExceptionSpec(
    Sema &S, SourceLocation Loc, CXXMethodDecl *MD, Sema::CXXSpecialMember CSM,
    Sema::InheritedConstructorInfo *ICI) {
  ComputingExceptionSpec CES(S, MD, Loc);

  CXXRecordDecl *ClassDecl = MD->getParent();

  // C++ [except.spec]p14:
  //   An implicitly declared special member function (Clause 12) shall have an
  //   exception-specification. [...]
  SpecialMemberExceptionSpecInfo Info(S, MD, CSM, ICI, MD->getLocation());
  if (ClassDecl->isInvalidDecl())
    return Info.ExceptSpec;

  // FIXME: If this diagnostic fires, we're probably missing a check for
  // attempting to resolve an exception specification before it's known
  // at a higher level.
  if (S.RequireCompleteType(MD->getLocation(),
                            S.Context.getRecordType(ClassDecl),
                            diag::err_exception_spec_incomplete_type))
    return Info.ExceptSpec;

  // C++1z [except.spec]p7:
  //   [Look for exceptions thrown by] a constructor selected [...] to
  //   initialize a potentially constructed subobject,
  // C++1z [except.spec]p8:
  //   The exception specification for an implicitly-declared destructor, or a
  //   destructor without a noexcept-specifier, is potentially-throwing if and
  //   only if any of the destructors for any of its potentially constructed
  //   subojects is potentially throwing.
  // FIXME: We respect the first rule but ignore the "potentially constructed"
  // in the second rule to resolve a core issue (no number yet) that would have
  // us reject:
  //   struct A { virtual void f() = 0; virtual ~A() noexcept(false) = 0; };
  //   struct B : A {};
  //   struct C : B { void f(); };
  // ... due to giving B::~B() a non-throwing exception specification.
  Info.visit(Info.IsConstructor ? Info.VisitPotentiallyConstructedBases
                                : Info.VisitAllBases);

  return Info.ExceptSpec;
}

namespace {
/// RAII object to register a special member as being currently declared.
struct DeclaringSpecialMember {
  Sema &S;
  Sema::SpecialMemberDecl D;
  Sema::ContextRAII SavedContext;
  bool WasAlreadyBeingDeclared;

  DeclaringSpecialMember(Sema &S, CXXRecordDecl *RD, Sema::CXXSpecialMember CSM)
      : S(S), D(RD, CSM), SavedContext(S, RD) {
    WasAlreadyBeingDeclared = !S.SpecialMembersBeingDeclared.insert(D).second;
    if (WasAlreadyBeingDeclared)
      // This almost never happens, but if it does, ensure that our cache
      // doesn't contain a stale result.
      S.SpecialMemberCache.clear();
    else {
      // Register a note to be produced if we encounter an error while
      // declaring the special member.
      Sema::CodeSynthesisContext Ctx;
      Ctx.Kind = Sema::CodeSynthesisContext::DeclaringSpecialMember;
      // FIXME: We don't have a location to use here. Using the class's
      // location maintains the fiction that we declare all special members
      // with the class, but (1) it's not clear that lying about that helps our
      // users understand what's going on, and (2) there may be outer contexts
      // on the stack (some of which are relevant) and printing them exposes
      // our lies.
      Ctx.PointOfInstantiation = RD->getLocation();
      Ctx.Entity = RD;
      Ctx.SpecialMember = CSM;
      S.pushCodeSynthesisContext(Ctx);
    }
  }
  ~DeclaringSpecialMember() {
    if (!WasAlreadyBeingDeclared) {
      S.SpecialMembersBeingDeclared.erase(D);
      S.popCodeSynthesisContext();
    }
  }

  /// Are we already trying to declare this special member?
  bool isAlreadyBeingDeclared() const {
    return WasAlreadyBeingDeclared;
  }
};
}

void Sema::CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD) {
  // Look up any existing declarations, but don't trigger declaration of all
  // implicit special members with this name.
  DeclarationName Name = FD->getDeclName();
  LookupResult R(*this, Name, SourceLocation(), LookupOrdinaryName,
                 ForExternalRedeclaration);
  for (auto *D : FD->getParent()->lookup(Name))
    if (auto *Acceptable = R.getAcceptableDecl(D))
      R.addDecl(Acceptable);
  R.resolveKind();
  R.suppressDiagnostics();

  CheckFunctionDeclaration(S, FD, R, /*IsMemberSpecialization*/false);
}

void Sema::setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
                                          QualType ResultTy,
                                          ArrayRef<QualType> Args) {
  // Build an exception specification pointing back at this constructor.
  FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, SpecialMem);

  if (getLangOpts().OpenCLCPlusPlus) {
    // OpenCL: Implicitly defaulted special member are of the generic address
    // space.
    EPI.TypeQuals.addAddressSpace(LangAS::opencl_generic);
  }

  auto QT = Context.getFunctionType(ResultTy, Args, EPI);
  SpecialMem->setType(QT);
}

CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor(
                                                     CXXRecordDecl *ClassDecl) {
  // C++ [class.ctor]p5:
  //   A default constructor for a class X is a constructor of class X
  //   that can be called without an argument. If there is no
  //   user-declared constructor for class X, a default constructor is
  //   implicitly declared. An implicitly-declared default constructor
  //   is an inline public member of its class.
  assert(ClassDecl->needsImplicitDefaultConstructor() &&
         "Should not build implicit default constructor!");

  DeclaringSpecialMember DSM(*this, ClassDecl, CXXDefaultConstructor);
  if (DSM.isAlreadyBeingDeclared())
    return nullptr;

  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
                                                     CXXDefaultConstructor,
                                                     false);

  // Create the actual constructor declaration.
  CanQualType ClassType
    = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
  SourceLocation ClassLoc = ClassDecl->getLocation();
  DeclarationName Name
    = Context.DeclarationNames.getCXXConstructorName(ClassType);
  DeclarationNameInfo NameInfo(Name, ClassLoc);
  CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create(
      Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(),
      /*TInfo=*/nullptr, ExplicitSpecifier(),
      /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr);
  DefaultCon->setAccess(AS_public);
  DefaultCon->setDefaulted();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDefaultConstructor,
                                            DefaultCon,
                                            /* ConstRHS */ false,
                                            /* Diagnose */ false);
  }

  setupImplicitSpecialMemberType(DefaultCon, Context.VoidTy, None);

  // We don't need to use SpecialMemberIsTrivial here; triviality for default
  // constructors is easy to compute.
  DefaultCon->setTrivial(ClassDecl->hasTrivialDefaultConstructor());

  // Note that we have declared this constructor.
  ++getASTContext().NumImplicitDefaultConstructorsDeclared;

  Scope *S = getScopeForContext(ClassDecl);
  CheckImplicitSpecialMemberDeclaration(S, DefaultCon);

  if (ShouldDeleteSpecialMember(DefaultCon, CXXDefaultConstructor))
    SetDeclDeleted(DefaultCon, ClassLoc);

  if (S)
    PushOnScopeChains(DefaultCon, S, false);
  ClassDecl->addDecl(DefaultCon);

  return DefaultCon;
}

void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
                                            CXXConstructorDecl *Constructor) {
  assert((Constructor->isDefaulted() && Constructor->isDefaultConstructor() &&
          !Constructor->doesThisDeclarationHaveABody() &&
          !Constructor->isDeleted()) &&
    "DefineImplicitDefaultConstructor - call it for implicit default ctor");
  if (Constructor->willHaveBody() || Constructor->isInvalidDecl())
    return;

  CXXRecordDecl *ClassDecl = Constructor->getParent();
  assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");

  SynthesizedFunctionScope Scope(*this, Constructor);

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       Constructor->getType()->castAs<FunctionProtoType>());
  MarkVTableUsed(CurrentLocation, ClassDecl);

  // Add a context note for diagnostics produced after this point.
  Scope.addContextNote(CurrentLocation);

  if (SetCtorInitializers(Constructor, /*AnyErrors=*/false)) {
    Constructor->setInvalidDecl();
    return;
  }

  SourceLocation Loc = Constructor->getEndLoc().isValid()
                           ? Constructor->getEndLoc()
                           : Constructor->getLocation();
  Constructor->setBody(new (Context) CompoundStmt(Loc));
  Constructor->markUsed(Context);

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Constructor);
  }

  DiagnoseUninitializedFields(*this, Constructor);
}

void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) {
  // Perform any delayed checks on exception specifications.
  CheckDelayedMemberExceptionSpecs();
}

/// Find or create the fake constructor we synthesize to model constructing an
/// object of a derived class via a constructor of a base class.
CXXConstructorDecl *
Sema::findInheritingConstructor(SourceLocation Loc,
                                CXXConstructorDecl *BaseCtor,
                                ConstructorUsingShadowDecl *Shadow) {
  CXXRecordDecl *Derived = Shadow->getParent();
  SourceLocation UsingLoc = Shadow->getLocation();

  // FIXME: Add a new kind of DeclarationName for an inherited constructor.
  // For now we use the name of the base class constructor as a member of the
  // derived class to indicate a (fake) inherited constructor name.
  DeclarationName Name = BaseCtor->getDeclName();

  // Check to see if we already have a fake constructor for this inherited
  // constructor call.
  for (NamedDecl *Ctor : Derived->lookup(Name))
    if (declaresSameEntity(cast<CXXConstructorDecl>(Ctor)
                               ->getInheritedConstructor()
                               .getConstructor(),
                           BaseCtor))
      return cast<CXXConstructorDecl>(Ctor);

  DeclarationNameInfo NameInfo(Name, UsingLoc);
  TypeSourceInfo *TInfo =
      Context.getTrivialTypeSourceInfo(BaseCtor->getType(), UsingLoc);
  FunctionProtoTypeLoc ProtoLoc =
      TInfo->getTypeLoc().IgnoreParens().castAs<FunctionProtoTypeLoc>();

  // Check the inherited constructor is valid and find the list of base classes
  // from which it was inherited.
  InheritedConstructorInfo ICI(*this, Loc, Shadow);

  bool Constexpr =
      BaseCtor->isConstexpr() &&
      defaultedSpecialMemberIsConstexpr(*this, Derived, CXXDefaultConstructor,
                                        false, BaseCtor, &ICI);

  CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create(
      Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo,
      BaseCtor->getExplicitSpecifier(), /*Inline=*/true,
      /*ImplicitlyDeclared=*/true, Constexpr,
      InheritedConstructor(Shadow, BaseCtor));
  if (Shadow->isInvalidDecl())
    DerivedCtor->setInvalidDecl();

  // Build an unevaluated exception specification for this fake constructor.
  const FunctionProtoType *FPT = TInfo->getType()->castAs<FunctionProtoType>();
  FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
  EPI.ExceptionSpec.Type = EST_Unevaluated;
  EPI.ExceptionSpec.SourceDecl = DerivedCtor;
  DerivedCtor->setType(Context.getFunctionType(FPT->getReturnType(),
                                               FPT->getParamTypes(), EPI));

  // Build the parameter declarations.
  SmallVector<ParmVarDecl *, 16> ParamDecls;
  for (unsigned I = 0, N = FPT->getNumParams(); I != N; ++I) {
    TypeSourceInfo *TInfo =
        Context.getTrivialTypeSourceInfo(FPT->getParamType(I), UsingLoc);
    ParmVarDecl *PD = ParmVarDecl::Create(
        Context, DerivedCtor, UsingLoc, UsingLoc, /*IdentifierInfo=*/nullptr,
        FPT->getParamType(I), TInfo, SC_None, /*DefaultArg=*/nullptr);
    PD->setScopeInfo(0, I);
    PD->setImplicit();
    // Ensure attributes are propagated onto parameters (this matters for
    // format, pass_object_size, ...).
    mergeDeclAttributes(PD, BaseCtor->getParamDecl(I));
    ParamDecls.push_back(PD);
    ProtoLoc.setParam(I, PD);
  }

  // Set up the new constructor.
  assert(!BaseCtor->isDeleted() && "should not use deleted constructor");
  DerivedCtor->setAccess(BaseCtor->getAccess());
  DerivedCtor->setParams(ParamDecls);
  Derived->addDecl(DerivedCtor);

  if (ShouldDeleteSpecialMember(DerivedCtor, CXXDefaultConstructor, &ICI))
    SetDeclDeleted(DerivedCtor, UsingLoc);

  return DerivedCtor;
}

void Sema::NoteDeletedInheritingConstructor(CXXConstructorDecl *Ctor) {
  InheritedConstructorInfo ICI(*this, Ctor->getLocation(),
                               Ctor->getInheritedConstructor().getShadowDecl());
  ShouldDeleteSpecialMember(Ctor, CXXDefaultConstructor, &ICI,
                            /*Diagnose*/true);
}

void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation,
                                       CXXConstructorDecl *Constructor) {
  CXXRecordDecl *ClassDecl = Constructor->getParent();
  assert(Constructor->getInheritedConstructor() &&
         !Constructor->doesThisDeclarationHaveABody() &&
         !Constructor->isDeleted());
  if (Constructor->willHaveBody() || Constructor->isInvalidDecl())
    return;

  // Initializations are performed "as if by a defaulted default constructor",
  // so enter the appropriate scope.
  SynthesizedFunctionScope Scope(*this, Constructor);

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       Constructor->getType()->castAs<FunctionProtoType>());
  MarkVTableUsed(CurrentLocation, ClassDecl);

  // Add a context note for diagnostics produced after this point.
  Scope.addContextNote(CurrentLocation);

  ConstructorUsingShadowDecl *Shadow =
      Constructor->getInheritedConstructor().getShadowDecl();
  CXXConstructorDecl *InheritedCtor =
      Constructor->getInheritedConstructor().getConstructor();

  // [class.inhctor.init]p1:
  //   initialization proceeds as if a defaulted default constructor is used to
  //   initialize the D object and each base class subobject from which the
  //   constructor was inherited

  InheritedConstructorInfo ICI(*this, CurrentLocation, Shadow);
  CXXRecordDecl *RD = Shadow->getParent();
  SourceLocation InitLoc = Shadow->getLocation();

  // Build explicit initializers for all base classes from which the
  // constructor was inherited.
  SmallVector<CXXCtorInitializer*, 8> Inits;
  for (bool VBase : {false, true}) {
    for (CXXBaseSpecifier &B : VBase ? RD->vbases() : RD->bases()) {
      if (B.isVirtual() != VBase)
        continue;

      auto *BaseRD = B.getType()->getAsCXXRecordDecl();
      if (!BaseRD)
        continue;

      auto BaseCtor = ICI.findConstructorForBase(BaseRD, InheritedCtor);
      if (!BaseCtor.first)
        continue;

      MarkFunctionReferenced(CurrentLocation, BaseCtor.first);
      ExprResult Init = new (Context) CXXInheritedCtorInitExpr(
          InitLoc, B.getType(), BaseCtor.first, VBase, BaseCtor.second);

      auto *TInfo = Context.getTrivialTypeSourceInfo(B.getType(), InitLoc);
      Inits.push_back(new (Context) CXXCtorInitializer(
          Context, TInfo, VBase, InitLoc, Init.get(), InitLoc,
          SourceLocation()));
    }
  }

  // We now proceed as if for a defaulted default constructor, with the relevant
  // initializers replaced.

  if (SetCtorInitializers(Constructor, /*AnyErrors*/false, Inits)) {
    Constructor->setInvalidDecl();
    return;
  }

  Constructor->setBody(new (Context) CompoundStmt(InitLoc));
  Constructor->markUsed(Context);

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Constructor);
  }

  DiagnoseUninitializedFields(*this, Constructor);
}

CXXDestructorDecl *Sema::DeclareImplicitDestructor(CXXRecordDecl *ClassDecl) {
  // C++ [class.dtor]p2:
  //   If a class has no user-declared destructor, a destructor is
  //   declared implicitly. An implicitly-declared destructor is an
  //   inline public member of its class.
  assert(ClassDecl->needsImplicitDestructor());

  DeclaringSpecialMember DSM(*this, ClassDecl, CXXDestructor);
  if (DSM.isAlreadyBeingDeclared())
    return nullptr;

  // Create the actual destructor declaration.
  CanQualType ClassType
    = Context.getCanonicalType(Context.getTypeDeclType(ClassDecl));
  SourceLocation ClassLoc = ClassDecl->getLocation();
  DeclarationName Name
    = Context.DeclarationNames.getCXXDestructorName(ClassType);
  DeclarationNameInfo NameInfo(Name, ClassLoc);
  CXXDestructorDecl *Destructor
      = CXXDestructorDecl::Create(Context, ClassDecl, ClassLoc, NameInfo,
                                  QualType(), nullptr, /*isInline=*/true,
                                  /*isImplicitlyDeclared=*/true);
  Destructor->setAccess(AS_public);
  Destructor->setDefaulted();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDestructor,
                                            Destructor,
                                            /* ConstRHS */ false,
                                            /* Diagnose */ false);
  }

  setupImplicitSpecialMemberType(Destructor, Context.VoidTy, None);

  // We don't need to use SpecialMemberIsTrivial here; triviality for
  // destructors is easy to compute.
  Destructor->setTrivial(ClassDecl->hasTrivialDestructor());
  Destructor->setTrivialForCall(ClassDecl->hasAttr<TrivialABIAttr>() ||
                                ClassDecl->hasTrivialDestructorForCall());

  // Note that we have declared this destructor.
  ++getASTContext().NumImplicitDestructorsDeclared;

  Scope *S = getScopeForContext(ClassDecl);
  CheckImplicitSpecialMemberDeclaration(S, Destructor);

  // We can't check whether an implicit destructor is deleted before we complete
  // the definition of the class, because its validity depends on the alignment
  // of the class. We'll check this from ActOnFields once the class is complete.
  if (ClassDecl->isCompleteDefinition() &&
      ShouldDeleteSpecialMember(Destructor, CXXDestructor))
    SetDeclDeleted(Destructor, ClassLoc);

  // Introduce this destructor into its scope.
  if (S)
    PushOnScopeChains(Destructor, S, false);
  ClassDecl->addDecl(Destructor);

  return Destructor;
}

void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation,
                                    CXXDestructorDecl *Destructor) {
  assert((Destructor->isDefaulted() &&
          !Destructor->doesThisDeclarationHaveABody() &&
          !Destructor->isDeleted()) &&
         "DefineImplicitDestructor - call it for implicit default dtor");
  if (Destructor->willHaveBody() || Destructor->isInvalidDecl())
    return;

  CXXRecordDecl *ClassDecl = Destructor->getParent();
  assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");

  SynthesizedFunctionScope Scope(*this, Destructor);

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       Destructor->getType()->castAs<FunctionProtoType>());
  MarkVTableUsed(CurrentLocation, ClassDecl);

  // Add a context note for diagnostics produced after this point.
  Scope.addContextNote(CurrentLocation);

  MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
                                         Destructor->getParent());

  if (CheckDestructor(Destructor)) {
    Destructor->setInvalidDecl();
    return;
  }

  SourceLocation Loc = Destructor->getEndLoc().isValid()
                           ? Destructor->getEndLoc()
                           : Destructor->getLocation();
  Destructor->setBody(new (Context) CompoundStmt(Loc));
  Destructor->markUsed(Context);

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Destructor);
  }
}

/// Perform any semantic analysis which needs to be delayed until all
/// pending class member declarations have been parsed.
void Sema::ActOnFinishCXXMemberDecls() {
  // If the context is an invalid C++ class, just suppress these checks.
  if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
    if (Record->isInvalidDecl()) {
      DelayedOverridingExceptionSpecChecks.clear();
      DelayedEquivalentExceptionSpecChecks.clear();
      return;
    }
    checkForMultipleExportedDefaultConstructors(*this, Record);
  }
}

void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
  referenceDLLExportedClassMethods();
}

void Sema::referenceDLLExportedClassMethods() {
  if (!DelayedDllExportClasses.empty()) {
    // Calling ReferenceDllExportedMembers might cause the current function to
    // be called again, so use a local copy of DelayedDllExportClasses.
    SmallVector<CXXRecordDecl *, 4> WorkList;
    std::swap(DelayedDllExportClasses, WorkList);
    for (CXXRecordDecl *Class : WorkList)
      ReferenceDllExportedMembers(*this, Class);
  }
}

void Sema::AdjustDestructorExceptionSpec(CXXDestructorDecl *Destructor) {
  assert(getLangOpts().CPlusPlus11 &&
         "adjusting dtor exception specs was introduced in c++11");

  if (Destructor->isDependentContext())
    return;

  // C++11 [class.dtor]p3:
  //   A declaration of a destructor that does not have an exception-
  //   specification is implicitly considered to have the same exception-
  //   specification as an implicit declaration.
  const FunctionProtoType *DtorType = Destructor->getType()->
                                        getAs<FunctionProtoType>();
  if (DtorType->hasExceptionSpec())
    return;

  // Replace the destructor's type, building off the existing one. Fortunately,
  // the only thing of interest in the destructor type is its extended info.
  // The return and arguments are fixed.
  FunctionProtoType::ExtProtoInfo EPI = DtorType->getExtProtoInfo();
  EPI.ExceptionSpec.Type = EST_Unevaluated;
  EPI.ExceptionSpec.SourceDecl = Destructor;
  Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI));

  // FIXME: If the destructor has a body that could throw, and the newly created
  // spec doesn't allow exceptions, we should emit a warning, because this
  // change in behavior can break conforming C++03 programs at runtime.
  // However, we don't have a body or an exception specification yet, so it
  // needs to be done somewhere else.
}

namespace {
/// An abstract base class for all helper classes used in building the
//  copy/move operators. These classes serve as factory functions and help us
//  avoid using the same Expr* in the AST twice.
class ExprBuilder {
  ExprBuilder(const ExprBuilder&) = delete;
  ExprBuilder &operator=(const ExprBuilder&) = delete;

protected:
  static Expr *assertNotNull(Expr *E) {
    assert(E && "Expression construction must not fail.");
    return E;
  }

public:
  ExprBuilder() {}
  virtual ~ExprBuilder() {}

  virtual Expr *build(Sema &S, SourceLocation Loc) const = 0;
};

class RefBuilder: public ExprBuilder {
  VarDecl *Var;
  QualType VarType;

public:
  Expr *build(Sema &S, SourceLocation Loc) const override {
    return assertNotNull(S.BuildDeclRefExpr(Var, VarType, VK_LValue, Loc).get());
  }

  RefBuilder(VarDecl *Var, QualType VarType)
      : Var(Var), VarType(VarType) {}
};

class ThisBuilder: public ExprBuilder {
public:
  Expr *build(Sema &S, SourceLocation Loc) const override {
    return assertNotNull(S.ActOnCXXThis(Loc).getAs<Expr>());
  }
};

class CastBuilder: public ExprBuilder {
  const ExprBuilder &Builder;
  QualType Type;
  ExprValueKind Kind;
  const CXXCastPath &Path;

public:
  Expr *build(Sema &S, SourceLocation Loc) const override {
    return assertNotNull(S.ImpCastExprToType(Builder.build(S, Loc), Type,
                                             CK_UncheckedDerivedToBase, Kind,
                                             &Path).get());
  }

  CastBuilder(const ExprBuilder &Builder, QualType Type, ExprValueKind Kind,
              const CXXCastPath &Path)
      : Builder(Builder), Type(Type), Kind(Kind), Path(Path) {}
};

class DerefBuilder: public ExprBuilder {
  const ExprBuilder &Builder;

public:
  Expr *build(Sema &S, SourceLocation Loc) const override {
    return assertNotNull(
        S.CreateBuiltinUnaryOp(Loc, UO_Deref, Builder.build(S, Loc)).get());
  }

  DerefBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
};

class MemberBuilder: public ExprBuilder {
  const ExprBuilder &Builder;
  QualType Type;
  CXXScopeSpec SS;
  bool IsArrow;
  LookupResult &MemberLookup;

public:
  Expr *build(Sema &S, SourceLocation Loc) const override {
    return assertNotNull(S.BuildMemberReferenceExpr(
        Builder.build(S, Loc), Type, Loc, IsArrow, SS, SourceLocation(),
        nullptr, MemberLookup, nullptr, nullptr).get());
  }

  MemberBuilder(const ExprBuilder &Builder, QualType Type, bool IsArrow,
                LookupResult &MemberLookup)
      : Builder(Builder), Type(Type), IsArrow(IsArrow),
        MemberLookup(MemberLookup) {}
};

class MoveCastBuilder: public ExprBuilder {
  const ExprBuilder &Builder;

public:
  Expr *build(Sema &S, SourceLocation Loc) const override {
    return assertNotNull(CastForMoving(S, Builder.build(S, Loc)));
  }

  MoveCastBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
};

class LvalueConvBuilder: public ExprBuilder {
  const ExprBuilder &Builder;

public:
  Expr *build(Sema &S, SourceLocation Loc) const override {
    return assertNotNull(
        S.DefaultLvalueConversion(Builder.build(S, Loc)).get());
  }

  LvalueConvBuilder(const ExprBuilder &Builder) : Builder(Builder) {}
};

class SubscriptBuilder: public ExprBuilder {
  const ExprBuilder &Base;
  const ExprBuilder &Index;

public:
  Expr *build(Sema &S, SourceLocation Loc) const override {
    return assertNotNull(S.CreateBuiltinArraySubscriptExpr(
        Base.build(S, Loc), Loc, Index.build(S, Loc), Loc).get());
  }

  SubscriptBuilder(const ExprBuilder &Base, const ExprBuilder &Index)
      : Base(Base), Index(Index) {}
};

} // end anonymous namespace

/// When generating a defaulted copy or move assignment operator, if a field
/// should be copied with __builtin_memcpy rather than via explicit assignments,
/// do so. This optimization only applies for arrays of scalars, and for arrays
/// of class type where the selected copy/move-assignment operator is trivial.
static StmtResult
buildMemcpyForAssignmentOp(Sema &S, SourceLocation Loc, QualType T,
                           const ExprBuilder &ToB, const ExprBuilder &FromB) {
  // Compute the size of the memory buffer to be copied.
  QualType SizeType = S.Context.getSizeType();
  llvm::APInt Size(S.Context.getTypeSize(SizeType),
                   S.Context.getTypeSizeInChars(T).getQuantity());

  // Take the address of the field references for "from" and "to". We
  // directly construct UnaryOperators here because semantic analysis
  // does not permit us to take the address of an xvalue.
  Expr *From = FromB.build(S, Loc);
  From = new (S.Context) UnaryOperator(From, UO_AddrOf,
                         S.Context.getPointerType(From->getType()),
                         VK_RValue, OK_Ordinary, Loc, false);
  Expr *To = ToB.build(S, Loc);
  To = new (S.Context) UnaryOperator(To, UO_AddrOf,
                       S.Context.getPointerType(To->getType()),
                       VK_RValue, OK_Ordinary, Loc, false);

  const Type *E = T->getBaseElementTypeUnsafe();
  bool NeedsCollectableMemCpy =
    E->isRecordType() && E->getAs<RecordType>()->getDecl()->hasObjectMember();

  // Create a reference to the __builtin_objc_memmove_collectable function
  StringRef MemCpyName = NeedsCollectableMemCpy ?
    "__builtin_objc_memmove_collectable" :
    "__builtin_memcpy";
  LookupResult R(S, &S.Context.Idents.get(MemCpyName), Loc,
                 Sema::LookupOrdinaryName);
  S.LookupName(R, S.TUScope, true);

  FunctionDecl *MemCpy = R.getAsSingle<FunctionDecl>();
  if (!MemCpy)
    // Something went horribly wrong earlier, and we will have complained
    // about it.
    return StmtError();

  ExprResult MemCpyRef = S.BuildDeclRefExpr(MemCpy, S.Context.BuiltinFnTy,
                                            VK_RValue, Loc, nullptr);
  assert(MemCpyRef.isUsable() && "Builtin reference cannot fail");

  Expr *CallArgs[] = {
    To, From, IntegerLiteral::Create(S.Context, Size, SizeType, Loc)
  };
  ExprResult Call = S.BuildCallExpr(/*Scope=*/nullptr, MemCpyRef.get(),
                                    Loc, CallArgs, Loc);

  assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
  return Call.getAs<Stmt>();
}

/// Builds a statement that copies/moves the given entity from \p From to
/// \c To.
///
/// This routine is used to copy/move the members of a class with an
/// implicitly-declared copy/move assignment operator. When the entities being
/// copied are arrays, this routine builds for loops to copy them.
///
/// \param S The Sema object used for type-checking.
///
/// \param Loc The location where the implicit copy/move is being generated.
///
/// \param T The type of the expressions being copied/moved. Both expressions
/// must have this type.
///
/// \param To The expression we are copying/moving to.
///
/// \param From The expression we are copying/moving from.
///
/// \param CopyingBaseSubobject Whether we're copying/moving a base subobject.
/// Otherwise, it's a non-static member subobject.
///
/// \param Copying Whether we're copying or moving.
///
/// \param Depth Internal parameter recording the depth of the recursion.
///
/// \returns A statement or a loop that copies the expressions, or StmtResult(0)
/// if a memcpy should be used instead.
static StmtResult
buildSingleCopyAssignRecursively(Sema &S, SourceLocation Loc, QualType T,
                                 const ExprBuilder &To, const ExprBuilder &From,
                                 bool CopyingBaseSubobject, bool Copying,
                                 unsigned Depth = 0) {
  // C++11 [class.copy]p28:
  //   Each subobject is assigned in the manner appropriate to its type:
  //
  //     - if the subobject is of class type, as if by a call to operator= with
  //       the subobject as the object expression and the corresponding
  //       subobject of x as a single function argument (as if by explicit
  //       qualification; that is, ignoring any possible virtual overriding
  //       functions in more derived classes);
  //
  // C++03 [class.copy]p13:
  //     - if the subobject is of class type, the copy assignment operator for
  //       the class is used (as if by explicit qualification; that is,
  //       ignoring any possible virtual overriding functions in more derived
  //       classes);
  if (const RecordType *RecordTy = T->getAs<RecordType>()) {
    CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(RecordTy->getDecl());

    // Look for operator=.
    DeclarationName Name
      = S.Context.DeclarationNames.getCXXOperatorName(OO_Equal);
    LookupResult OpLookup(S, Name, Loc, Sema::LookupOrdinaryName);
    S.LookupQualifiedName(OpLookup, ClassDecl, false);

    // Prior to C++11, filter out any result that isn't a copy/move-assignment
    // operator.
    if (!S.getLangOpts().CPlusPlus11) {
      LookupResult::Filter F = OpLookup.makeFilter();
      while (F.hasNext()) {
        NamedDecl *D = F.next();
        if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
          if (Method->isCopyAssignmentOperator() ||
              (!Copying && Method->isMoveAssignmentOperator()))
            continue;

        F.erase();
      }
      F.done();
    }

    // Suppress the protected check (C++ [class.protected]) for each of the
    // assignment operators we found. This strange dance is required when
    // we're assigning via a base classes's copy-assignment operator. To
    // ensure that we're getting the right base class subobject (without
    // ambiguities), we need to cast "this" to that subobject type; to
    // ensure that we don't go through the virtual call mechanism, we need
    // to qualify the operator= name with the base class (see below). However,
    // this means that if the base class has a protected copy assignment
    // operator, the protected member access check will fail. So, we
    // rewrite "protected" access to "public" access in this case, since we
    // know by construction that we're calling from a derived class.
    if (CopyingBaseSubobject) {
      for (LookupResult::iterator L = OpLookup.begin(), LEnd = OpLookup.end();
           L != LEnd; ++L) {
        if (L.getAccess() == AS_protected)
          L.setAccess(AS_public);
      }
    }

    // Create the nested-name-specifier that will be used to qualify the
    // reference to operator=; this is required to suppress the virtual
    // call mechanism.
    CXXScopeSpec SS;
    const Type *CanonicalT = S.Context.getCanonicalType(T.getTypePtr());
    SS.MakeTrivial(S.Context,
                   NestedNameSpecifier::Create(S.Context, nullptr, false,
                                               CanonicalT),
                   Loc);

    // Create the reference to operator=.
    ExprResult OpEqualRef
      = S.BuildMemberReferenceExpr(To.build(S, Loc), T, Loc, /*isArrow=*/false,
                                   SS, /*TemplateKWLoc=*/SourceLocation(),
                                   /*FirstQualifierInScope=*/nullptr,
                                   OpLookup,
                                   /*TemplateArgs=*/nullptr, /*S*/nullptr,
                                   /*SuppressQualifierCheck=*/true);
    if (OpEqualRef.isInvalid())
      return StmtError();

    // Build the call to the assignment operator.

    Expr *FromInst = From.build(S, Loc);
    ExprResult Call = S.BuildCallToMemberFunction(/*Scope=*/nullptr,
                                                  OpEqualRef.getAs<Expr>(),
                                                  Loc, FromInst, Loc);
    if (Call.isInvalid())
      return StmtError();

    // If we built a call to a trivial 'operator=' while copying an array,
    // bail out. We'll replace the whole shebang with a memcpy.
    CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(Call.get());
    if (CE && CE->getMethodDecl()->isTrivial() && Depth)
      return StmtResult((Stmt*)nullptr);

    // Convert to an expression-statement, and clean up any produced
    // temporaries.
    return S.ActOnExprStmt(Call);
  }

  //     - if the subobject is of scalar type, the built-in assignment
  //       operator is used.
  const ConstantArrayType *ArrayTy = S.Context.getAsConstantArrayType(T);
  if (!ArrayTy) {
    ExprResult Assignment = S.CreateBuiltinBinOp(
        Loc, BO_Assign, To.build(S, Loc), From.build(S, Loc));
    if (Assignment.isInvalid())
      return StmtError();
    return S.ActOnExprStmt(Assignment);
  }

  //     - if the subobject is an array, each element is assigned, in the
  //       manner appropriate to the element type;

  // Construct a loop over the array bounds, e.g.,
  //
  //   for (__SIZE_TYPE__ i0 = 0; i0 != array-size; ++i0)
  //
  // that will copy each of the array elements.
  QualType SizeType = S.Context.getSizeType();

  // Create the iteration variable.
  IdentifierInfo *IterationVarName = nullptr;
  {
    SmallString<8> Str;
    llvm::raw_svector_ostream OS(Str);
    OS << "__i" << Depth;
    IterationVarName = &S.Context.Idents.get(OS.str());
  }
  VarDecl *IterationVar = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
                                          IterationVarName, SizeType,
                            S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
                                          SC_None);

  // Initialize the iteration variable to zero.
  llvm::APInt Zero(S.Context.getTypeSize(SizeType), 0);
  IterationVar->setInit(IntegerLiteral::Create(S.Context, Zero, SizeType, Loc));

  // Creates a reference to the iteration variable.
  RefBuilder IterationVarRef(IterationVar, SizeType);
  LvalueConvBuilder IterationVarRefRVal(IterationVarRef);

  // Create the DeclStmt that holds the iteration variable.
  Stmt *InitStmt = new (S.Context) DeclStmt(DeclGroupRef(IterationVar),Loc,Loc);

  // Subscript the "from" and "to" expressions with the iteration variable.
  SubscriptBuilder FromIndexCopy(From, IterationVarRefRVal);
  MoveCastBuilder FromIndexMove(FromIndexCopy);
  const ExprBuilder *FromIndex;
  if (Copying)
    FromIndex = &FromIndexCopy;
  else
    FromIndex = &FromIndexMove;

  SubscriptBuilder ToIndex(To, IterationVarRefRVal);

  // Build the copy/move for an individual element of the array.
  StmtResult Copy =
    buildSingleCopyAssignRecursively(S, Loc, ArrayTy->getElementType(),
                                     ToIndex, *FromIndex, CopyingBaseSubobject,
                                     Copying, Depth + 1);
  // Bail out if copying fails or if we determined that we should use memcpy.
  if (Copy.isInvalid() || !Copy.get())
    return Copy;

  // Create the comparison against the array bound.
  llvm::APInt Upper
    = ArrayTy->getSize().zextOrTrunc(S.Context.getTypeSize(SizeType));
  Expr *Comparison
    = new (S.Context) BinaryOperator(IterationVarRefRVal.build(S, Loc),
                     IntegerLiteral::Create(S.Context, Upper, SizeType, Loc),
                                     BO_NE, S.Context.BoolTy,
                                     VK_RValue, OK_Ordinary, Loc, FPOptions());

  // Create the pre-increment of the iteration variable. We can determine
  // whether the increment will overflow based on the value of the array
  // bound.
  Expr *Increment = new (S.Context)
      UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc, SizeType,
                    VK_LValue, OK_Ordinary, Loc, Upper.isMaxValue());

  // Construct the loop that copies all elements of this array.
  return S.ActOnForStmt(
      Loc, Loc, InitStmt,
      S.ActOnCondition(nullptr, Loc, Comparison, Sema::ConditionKind::Boolean),
      S.MakeFullDiscardedValueExpr(Increment), Loc, Copy.get());
}

static StmtResult
buildSingleCopyAssign(Sema &S, SourceLocation Loc, QualType T,
                      const ExprBuilder &To, const ExprBuilder &From,
                      bool CopyingBaseSubobject, bool Copying) {
  // Maybe we should use a memcpy?
  if (T->isArrayType() && !T.isConstQualified() && !T.isVolatileQualified() &&
      T.isTriviallyCopyableType(S.Context))
    return buildMemcpyForAssignmentOp(S, Loc, T, To, From);

  StmtResult Result(buildSingleCopyAssignRecursively(S, Loc, T, To, From,
                                                     CopyingBaseSubobject,
                                                     Copying, 0));

  // If we ended up picking a trivial assignment operator for an array of a
  // non-trivially-copyable class type, just emit a memcpy.
  if (!Result.isInvalid() && !Result.get())
    return buildMemcpyForAssignmentOp(S, Loc, T, To, From);

  return Result;
}

CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) {
  // Note: The following rules are largely analoguous to the copy
  // constructor rules. Note that virtual bases are not taken into account
  // for determining the argument type of the operator. Note also that
  // operators taking an object instead of a reference are allowed.
  assert(ClassDecl->needsImplicitCopyAssignment());

  DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyAssignment);
  if (DSM.isAlreadyBeingDeclared())
    return nullptr;

  QualType ArgType = Context.getTypeDeclType(ClassDecl);
  if (Context.getLangOpts().OpenCLCPlusPlus)
    ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
  QualType RetType = Context.getLValueReferenceType(ArgType);
  bool Const = ClassDecl->implicitCopyAssignmentHasConstParam();
  if (Const)
    ArgType = ArgType.withConst();

  ArgType = Context.getLValueReferenceType(ArgType);

  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
                                                     CXXCopyAssignment,
                                                     Const);

  //   An implicitly-declared copy assignment operator is an inline public
  //   member of its class.
  DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
  SourceLocation ClassLoc = ClassDecl->getLocation();
  DeclarationNameInfo NameInfo(Name, ClassLoc);
  CXXMethodDecl *CopyAssignment =
      CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
                            /*TInfo=*/nullptr, /*StorageClass=*/SC_None,
                            /*isInline=*/true, Constexpr, SourceLocation());
  CopyAssignment->setAccess(AS_public);
  CopyAssignment->setDefaulted();
  CopyAssignment->setImplicit();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyAssignment,
                                            CopyAssignment,
                                            /* ConstRHS */ Const,
                                            /* Diagnose */ false);
  }

  setupImplicitSpecialMemberType(CopyAssignment, RetType, ArgType);

  // Add the parameter to the operator.
  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyAssignment,
                                               ClassLoc, ClassLoc,
                                               /*Id=*/nullptr, ArgType,
                                               /*TInfo=*/nullptr, SC_None,
                                               nullptr);
  CopyAssignment->setParams(FromParam);

  CopyAssignment->setTrivial(
    ClassDecl->needsOverloadResolutionForCopyAssignment()
      ? SpecialMemberIsTrivial(CopyAssignment, CXXCopyAssignment)
      : ClassDecl->hasTrivialCopyAssignment());

  // Note that we have added this copy-assignment operator.
  ++getASTContext().NumImplicitCopyAssignmentOperatorsDeclared;

  Scope *S = getScopeForContext(ClassDecl);
  CheckImplicitSpecialMemberDeclaration(S, CopyAssignment);

  if (ShouldDeleteSpecialMember(CopyAssignment, CXXCopyAssignment))
    SetDeclDeleted(CopyAssignment, ClassLoc);

  if (S)
    PushOnScopeChains(CopyAssignment, S, false);
  ClassDecl->addDecl(CopyAssignment);

  return CopyAssignment;
}

/// Diagnose an implicit copy operation for a class which is odr-used, but
/// which is deprecated because the class has a user-declared copy constructor,
/// copy assignment operator, or destructor.
static void diagnoseDeprecatedCopyOperation(Sema &S, CXXMethodDecl *CopyOp) {
  assert(CopyOp->isImplicit());

  CXXRecordDecl *RD = CopyOp->getParent();
  CXXMethodDecl *UserDeclaredOperation = nullptr;

  // In Microsoft mode, assignment operations don't affect constructors and
  // vice versa.
  if (RD->hasUserDeclaredDestructor()) {
    UserDeclaredOperation = RD->getDestructor();
  } else if (!isa<CXXConstructorDecl>(CopyOp) &&
             RD->hasUserDeclaredCopyConstructor() &&
             !S.getLangOpts().MSVCCompat) {
    // Find any user-declared copy constructor.
    for (auto *I : RD->ctors()) {
      if (I->isCopyConstructor()) {
        UserDeclaredOperation = I;
        break;
      }
    }
    assert(UserDeclaredOperation);
  } else if (isa<CXXConstructorDecl>(CopyOp) &&
             RD->hasUserDeclaredCopyAssignment() &&
             !S.getLangOpts().MSVCCompat) {
    // Find any user-declared move assignment operator.
    for (auto *I : RD->methods()) {
      if (I->isCopyAssignmentOperator()) {
        UserDeclaredOperation = I;
        break;
      }
    }
    assert(UserDeclaredOperation);
  }

  if (UserDeclaredOperation) {
    S.Diag(UserDeclaredOperation->getLocation(),
         diag::warn_deprecated_copy_operation)
      << RD << /*copy assignment*/!isa<CXXConstructorDecl>(CopyOp)
      << /*destructor*/isa<CXXDestructorDecl>(UserDeclaredOperation);
  }
}

void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation,
                                        CXXMethodDecl *CopyAssignOperator) {
  assert((CopyAssignOperator->isDefaulted() &&
          CopyAssignOperator->isOverloadedOperator() &&
          CopyAssignOperator->getOverloadedOperator() == OO_Equal &&
          !CopyAssignOperator->doesThisDeclarationHaveABody() &&
          !CopyAssignOperator->isDeleted()) &&
         "DefineImplicitCopyAssignment called for wrong function");
  if (CopyAssignOperator->willHaveBody() || CopyAssignOperator->isInvalidDecl())
    return;

  CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();
  if (ClassDecl->isInvalidDecl()) {
    CopyAssignOperator->setInvalidDecl();
    return;
  }

  SynthesizedFunctionScope Scope(*this, CopyAssignOperator);

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       CopyAssignOperator->getType()->castAs<FunctionProtoType>());

  // Add a context note for diagnostics produced after this point.
  Scope.addContextNote(CurrentLocation);

  // C++11 [class.copy]p18:
  //   The [definition of an implicitly declared copy assignment operator] is
  //   deprecated if the class has a user-declared copy constructor or a
  //   user-declared destructor.
  if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit())
    diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator);

  // C++0x [class.copy]p30:
  //   The implicitly-defined or explicitly-defaulted copy assignment operator
  //   for a non-union class X performs memberwise copy assignment of its
  //   subobjects. The direct base classes of X are assigned first, in the
  //   order of their declaration in the base-specifier-list, and then the
  //   immediate non-static data members of X are assigned, in the order in
  //   which they were declared in the class definition.

  // The statements that form the synthesized function body.
  SmallVector<Stmt*, 8> Statements;

  // The parameter for the "other" object, which we are copying from.
  ParmVarDecl *Other = CopyAssignOperator->getParamDecl(0);
  Qualifiers OtherQuals = Other->getType().getQualifiers();
  QualType OtherRefType = Other->getType();
  if (const LValueReferenceType *OtherRef
                                = OtherRefType->getAs<LValueReferenceType>()) {
    OtherRefType = OtherRef->getPointeeType();
    OtherQuals = OtherRefType.getQualifiers();
  }

  // Our location for everything implicitly-generated.
  SourceLocation Loc = CopyAssignOperator->getEndLoc().isValid()
                           ? CopyAssignOperator->getEndLoc()
                           : CopyAssignOperator->getLocation();

  // Builds a DeclRefExpr for the "other" object.
  RefBuilder OtherRef(Other, OtherRefType);

  // Builds the "this" pointer.
  ThisBuilder This;

  // Assign base classes.
  bool Invalid = false;
  for (auto &Base : ClassDecl->bases()) {
    // Form the assignment:
    //   static_cast<Base*>(this)->Base::operator=(static_cast<Base&>(other));
    QualType BaseType = Base.getType().getUnqualifiedType();
    if (!BaseType->isRecordType()) {
      Invalid = true;
      continue;
    }

    CXXCastPath BasePath;
    BasePath.push_back(&Base);

    // Construct the "from" expression, which is an implicit cast to the
    // appropriately-qualified base type.
    CastBuilder From(OtherRef, Context.getQualifiedType(BaseType, OtherQuals),
                     VK_LValue, BasePath);

    // Dereference "this".
    DerefBuilder DerefThis(This);
    CastBuilder To(DerefThis,
                   Context.getQualifiedType(
                       BaseType, CopyAssignOperator->getMethodQualifiers()),
                   VK_LValue, BasePath);

    // Build the copy.
    StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType,
                                            To, From,
                                            /*CopyingBaseSubobject=*/true,
                                            /*Copying=*/true);
    if (Copy.isInvalid()) {
      CopyAssignOperator->setInvalidDecl();
      return;
    }

    // Success! Record the copy.
    Statements.push_back(Copy.getAs<Expr>());
  }

  // Assign non-static members.
  for (auto *Field : ClassDecl->fields()) {
    // FIXME: We should form some kind of AST representation for the implied
    // memcpy in a union copy operation.
    if (Field->isUnnamedBitfield() || Field->getParent()->isUnion())
      continue;

    if (Field->isInvalidDecl()) {
      Invalid = true;
      continue;
    }

    // Check for members of reference type; we can't copy those.
    if (Field->getType()->isReferenceType()) {
      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
        << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
      Diag(Field->getLocation(), diag::note_declared_at);
      Invalid = true;
      continue;
    }

    // Check for members of const-qualified, non-class type.
    QualType BaseType = Context.getBaseElementType(Field->getType());
    if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
        << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
      Diag(Field->getLocation(), diag::note_declared_at);
      Invalid = true;
      continue;
    }

    // Suppress assigning zero-width bitfields.
    if (Field->isZeroLengthBitField(Context))
      continue;

    QualType FieldType = Field->getType().getNonReferenceType();
    if (FieldType->isIncompleteArrayType()) {
      assert(ClassDecl->hasFlexibleArrayMember() &&
             "Incomplete array type is not valid");
      continue;
    }

    // Build references to the field in the object we're copying from and to.
    CXXScopeSpec SS; // Intentionally empty
    LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
                              LookupMemberName);
    MemberLookup.addDecl(Field);
    MemberLookup.resolveKind();

    MemberBuilder From(OtherRef, OtherRefType, /*IsArrow=*/false, MemberLookup);

    MemberBuilder To(This, getCurrentThisType(), /*IsArrow=*/true, MemberLookup);

    // Build the copy of this field.
    StmtResult Copy = buildSingleCopyAssign(*this, Loc, FieldType,
                                            To, From,
                                            /*CopyingBaseSubobject=*/false,
                                            /*Copying=*/true);
    if (Copy.isInvalid()) {
      CopyAssignOperator->setInvalidDecl();
      return;
    }

    // Success! Record the copy.
    Statements.push_back(Copy.getAs<Stmt>());
  }

  if (!Invalid) {
    // Add a "return *this;"
    ExprResult ThisObj = CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));

    StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
    if (Return.isInvalid())
      Invalid = true;
    else
      Statements.push_back(Return.getAs<Stmt>());
  }

  if (Invalid) {
    CopyAssignOperator->setInvalidDecl();
    return;
  }

  StmtResult Body;
  {
    CompoundScopeRAII CompoundScope(*this);
    Body = ActOnCompoundStmt(Loc, Loc, Statements,
                             /*isStmtExpr=*/false);
    assert(!Body.isInvalid() && "Compound statement creation cannot fail");
  }
  CopyAssignOperator->setBody(Body.getAs<Stmt>());
  CopyAssignOperator->markUsed(Context);

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(CopyAssignOperator);
  }
}

CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) {
  assert(ClassDecl->needsImplicitMoveAssignment());

  DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveAssignment);
  if (DSM.isAlreadyBeingDeclared())
    return nullptr;

  // Note: The following rules are largely analoguous to the move
  // constructor rules.

  QualType ArgType = Context.getTypeDeclType(ClassDecl);
  if (Context.getLangOpts().OpenCLCPlusPlus)
    ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
  QualType RetType = Context.getLValueReferenceType(ArgType);
  ArgType = Context.getRValueReferenceType(ArgType);

  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
                                                     CXXMoveAssignment,
                                                     false);

  //   An implicitly-declared move assignment operator is an inline public
  //   member of its class.
  DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal);
  SourceLocation ClassLoc = ClassDecl->getLocation();
  DeclarationNameInfo NameInfo(Name, ClassLoc);
  CXXMethodDecl *MoveAssignment =
      CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(),
                            /*TInfo=*/nullptr, /*StorageClass=*/SC_None,
                            /*isInline=*/true, Constexpr, SourceLocation());
  MoveAssignment->setAccess(AS_public);
  MoveAssignment->setDefaulted();
  MoveAssignment->setImplicit();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveAssignment,
                                            MoveAssignment,
                                            /* ConstRHS */ false,
                                            /* Diagnose */ false);
  }

  // Build an exception specification pointing back at this member.
  FunctionProtoType::ExtProtoInfo EPI =
      getImplicitMethodEPI(*this, MoveAssignment);
  MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));

  // Add the parameter to the operator.
  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
                                               ClassLoc, ClassLoc,
                                               /*Id=*/nullptr, ArgType,
                                               /*TInfo=*/nullptr, SC_None,
                                               nullptr);
  MoveAssignment->setParams(FromParam);

  MoveAssignment->setTrivial(
    ClassDecl->needsOverloadResolutionForMoveAssignment()
      ? SpecialMemberIsTrivial(MoveAssignment, CXXMoveAssignment)
      : ClassDecl->hasTrivialMoveAssignment());

  // Note that we have added this copy-assignment operator.
  ++getASTContext().NumImplicitMoveAssignmentOperatorsDeclared;

  Scope *S = getScopeForContext(ClassDecl);
  CheckImplicitSpecialMemberDeclaration(S, MoveAssignment);

  if (ShouldDeleteSpecialMember(MoveAssignment, CXXMoveAssignment)) {
    ClassDecl->setImplicitMoveAssignmentIsDeleted();
    SetDeclDeleted(MoveAssignment, ClassLoc);
  }

  if (S)
    PushOnScopeChains(MoveAssignment, S, false);
  ClassDecl->addDecl(MoveAssignment);

  return MoveAssignment;
}

/// Check if we're implicitly defining a move assignment operator for a class
/// with virtual bases. Such a move assignment might move-assign the virtual
/// base multiple times.
static void checkMoveAssignmentForRepeatedMove(Sema &S, CXXRecordDecl *Class,
                                               SourceLocation CurrentLocation) {
  assert(!Class->isDependentContext() && "should not define dependent move");

  // Only a virtual base could get implicitly move-assigned multiple times.
  // Only a non-trivial move assignment can observe this. We only want to
  // diagnose if we implicitly define an assignment operator that assigns
  // two base classes, both of which move-assign the same virtual base.
  if (Class->getNumVBases() == 0 || Class->hasTrivialMoveAssignment() ||
      Class->getNumBases() < 2)
    return;

  llvm::SmallVector<CXXBaseSpecifier *, 16> Worklist;
  typedef llvm::DenseMap<CXXRecordDecl*, CXXBaseSpecifier*> VBaseMap;
  VBaseMap VBases;

  for (auto &BI : Class->bases()) {
    Worklist.push_back(&BI);
    while (!Worklist.empty()) {
      CXXBaseSpecifier *BaseSpec = Worklist.pop_back_val();
      CXXRecordDecl *Base = BaseSpec->getType()->getAsCXXRecordDecl();

      // If the base has no non-trivial move assignment operators,
      // we don't care about moves from it.
      if (!Base->hasNonTrivialMoveAssignment())
        continue;

      // If there's nothing virtual here, skip it.
      if (!BaseSpec->isVirtual() && !Base->getNumVBases())
        continue;

      // If we're not actually going to call a move assignment for this base,
      // or the selected move assignment is trivial, skip it.
      Sema::SpecialMemberOverloadResult SMOR =
        S.LookupSpecialMember(Base, Sema::CXXMoveAssignment,
                              /*ConstArg*/false, /*VolatileArg*/false,
                              /*RValueThis*/true, /*ConstThis*/false,
                              /*VolatileThis*/false);
      if (!SMOR.getMethod() || SMOR.getMethod()->isTrivial() ||
          !SMOR.getMethod()->isMoveAssignmentOperator())
        continue;

      if (BaseSpec->isVirtual()) {
        // We're going to move-assign this virtual base, and its move
        // assignment operator is not trivial. If this can happen for
        // multiple distinct direct bases of Class, diagnose it. (If it
        // only happens in one base, we'll diagnose it when synthesizing
        // that base class's move assignment operator.)
        CXXBaseSpecifier *&Existing =
            VBases.insert(std::make_pair(Base->getCanonicalDecl(), &BI))
                .first->second;
        if (Existing && Existing != &BI) {
          S.Diag(CurrentLocation, diag::warn_vbase_moved_multiple_times)
            << Class << Base;
          S.Diag(Existing->getBeginLoc(), diag::note_vbase_moved_here)
              << (Base->getCanonicalDecl() ==
                  Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
              << Base << Existing->getType() << Existing->getSourceRange();
          S.Diag(BI.getBeginLoc(), diag::note_vbase_moved_here)
              << (Base->getCanonicalDecl() ==
                  BI.getType()->getAsCXXRecordDecl()->getCanonicalDecl())
              << Base << BI.getType() << BaseSpec->getSourceRange();

          // Only diagnose each vbase once.
          Existing = nullptr;
        }
      } else {
        // Only walk over bases that have defaulted move assignment operators.
        // We assume that any user-provided move assignment operator handles
        // the multiple-moves-of-vbase case itself somehow.
        if (!SMOR.getMethod()->isDefaulted())
          continue;

        // We're going to move the base classes of Base. Add them to the list.
        for (auto &BI : Base->bases())
          Worklist.push_back(&BI);
      }
    }
  }
}

void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation,
                                        CXXMethodDecl *MoveAssignOperator) {
  assert((MoveAssignOperator->isDefaulted() &&
          MoveAssignOperator->isOverloadedOperator() &&
          MoveAssignOperator->getOverloadedOperator() == OO_Equal &&
          !MoveAssignOperator->doesThisDeclarationHaveABody() &&
          !MoveAssignOperator->isDeleted()) &&
         "DefineImplicitMoveAssignment called for wrong function");
  if (MoveAssignOperator->willHaveBody() || MoveAssignOperator->isInvalidDecl())
    return;

  CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent();
  if (ClassDecl->isInvalidDecl()) {
    MoveAssignOperator->setInvalidDecl();
    return;
  }

  // C++0x [class.copy]p28:
  //   The implicitly-defined or move assignment operator for a non-union class
  //   X performs memberwise move assignment of its subobjects. The direct base
  //   classes of X are assigned first, in the order of their declaration in the
  //   base-specifier-list, and then the immediate non-static data members of X
  //   are assigned, in the order in which they were declared in the class
  //   definition.

  // Issue a warning if our implicit move assignment operator will move
  // from a virtual base more than once.
  checkMoveAssignmentForRepeatedMove(*this, ClassDecl, CurrentLocation);

  SynthesizedFunctionScope Scope(*this, MoveAssignOperator);

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       MoveAssignOperator->getType()->castAs<FunctionProtoType>());

  // Add a context note for diagnostics produced after this point.
  Scope.addContextNote(CurrentLocation);

  // The statements that form the synthesized function body.
  SmallVector<Stmt*, 8> Statements;

  // The parameter for the "other" object, which we are move from.
  ParmVarDecl *Other = MoveAssignOperator->getParamDecl(0);
  QualType OtherRefType = Other->getType()->
      getAs<RValueReferenceType>()->getPointeeType();

  // Our location for everything implicitly-generated.
  SourceLocation Loc = MoveAssignOperator->getEndLoc().isValid()
                           ? MoveAssignOperator->getEndLoc()
                           : MoveAssignOperator->getLocation();

  // Builds a reference to the "other" object.
  RefBuilder OtherRef(Other, OtherRefType);
  // Cast to rvalue.
  MoveCastBuilder MoveOther(OtherRef);

  // Builds the "this" pointer.
  ThisBuilder This;

  // Assign base classes.
  bool Invalid = false;
  for (auto &Base : ClassDecl->bases()) {
    // C++11 [class.copy]p28:
    //   It is unspecified whether subobjects representing virtual base classes
    //   are assigned more than once by the implicitly-defined copy assignment
    //   operator.
    // FIXME: Do not assign to a vbase that will be assigned by some other base
    // class. For a move-assignment, this can result in the vbase being moved
    // multiple times.

    // Form the assignment:
    //   static_cast<Base*>(this)->Base::operator=(static_cast<Base&&>(other));
    QualType BaseType = Base.getType().getUnqualifiedType();
    if (!BaseType->isRecordType()) {
      Invalid = true;
      continue;
    }

    CXXCastPath BasePath;
    BasePath.push_back(&Base);

    // Construct the "from" expression, which is an implicit cast to the
    // appropriately-qualified base type.
    CastBuilder From(OtherRef, BaseType, VK_XValue, BasePath);

    // Dereference "this".
    DerefBuilder DerefThis(This);

    // Implicitly cast "this" to the appropriately-qualified base type.
    CastBuilder To(DerefThis,
                   Context.getQualifiedType(
                       BaseType, MoveAssignOperator->getMethodQualifiers()),
                   VK_LValue, BasePath);

    // Build the move.
    StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType,
                                            To, From,
                                            /*CopyingBaseSubobject=*/true,
                                            /*Copying=*/false);
    if (Move.isInvalid()) {
      MoveAssignOperator->setInvalidDecl();
      return;
    }

    // Success! Record the move.
    Statements.push_back(Move.getAs<Expr>());
  }

  // Assign non-static members.
  for (auto *Field : ClassDecl->fields()) {
    // FIXME: We should form some kind of AST representation for the implied
    // memcpy in a union copy operation.
    if (Field->isUnnamedBitfield() || Field->getParent()->isUnion())
      continue;

    if (Field->isInvalidDecl()) {
      Invalid = true;
      continue;
    }

    // Check for members of reference type; we can't move those.
    if (Field->getType()->isReferenceType()) {
      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
        << Context.getTagDeclType(ClassDecl) << 0 << Field->getDeclName();
      Diag(Field->getLocation(), diag::note_declared_at);
      Invalid = true;
      continue;
    }

    // Check for members of const-qualified, non-class type.
    QualType BaseType = Context.getBaseElementType(Field->getType());
    if (!BaseType->getAs<RecordType>() && BaseType.isConstQualified()) {
      Diag(ClassDecl->getLocation(), diag::err_uninitialized_member_for_assign)
        << Context.getTagDeclType(ClassDecl) << 1 << Field->getDeclName();
      Diag(Field->getLocation(), diag::note_declared_at);
      Invalid = true;
      continue;
    }

    // Suppress assigning zero-width bitfields.
    if (Field->isZeroLengthBitField(Context))
      continue;

    QualType FieldType = Field->getType().getNonReferenceType();
    if (FieldType->isIncompleteArrayType()) {
      assert(ClassDecl->hasFlexibleArrayMember() &&
             "Incomplete array type is not valid");
      continue;
    }

    // Build references to the field in the object we're copying from and to.
    LookupResult MemberLookup(*this, Field->getDeclName(), Loc,
                              LookupMemberName);
    MemberLookup.addDecl(Field);
    MemberLookup.resolveKind();
    MemberBuilder From(MoveOther, OtherRefType,
                       /*IsArrow=*/false, MemberLookup);
    MemberBuilder To(This, getCurrentThisType(),
                     /*IsArrow=*/true, MemberLookup);

    assert(!From.build(*this, Loc)->isLValue() && // could be xvalue or prvalue
        "Member reference with rvalue base must be rvalue except for reference "
        "members, which aren't allowed for move assignment.");

    // Build the move of this field.
    StmtResult Move = buildSingleCopyAssign(*this, Loc, FieldType,
                                            To, From,
                                            /*CopyingBaseSubobject=*/false,
                                            /*Copying=*/false);
    if (Move.isInvalid()) {
      MoveAssignOperator->setInvalidDecl();
      return;
    }

    // Success! Record the copy.
    Statements.push_back(Move.getAs<Stmt>());
  }

  if (!Invalid) {
    // Add a "return *this;"
    ExprResult ThisObj =
        CreateBuiltinUnaryOp(Loc, UO_Deref, This.build(*this, Loc));

    StmtResult Return = BuildReturnStmt(Loc, ThisObj.get());
    if (Return.isInvalid())
      Invalid = true;
    else
      Statements.push_back(Return.getAs<Stmt>());
  }

  if (Invalid) {
    MoveAssignOperator->setInvalidDecl();
    return;
  }

  StmtResult Body;
  {
    CompoundScopeRAII CompoundScope(*this);
    Body = ActOnCompoundStmt(Loc, Loc, Statements,
                             /*isStmtExpr=*/false);
    assert(!Body.isInvalid() && "Compound statement creation cannot fail");
  }
  MoveAssignOperator->setBody(Body.getAs<Stmt>());
  MoveAssignOperator->markUsed(Context);

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(MoveAssignOperator);
  }
}

CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor(
                                                    CXXRecordDecl *ClassDecl) {
  // C++ [class.copy]p4:
  //   If the class definition does not explicitly declare a copy
  //   constructor, one is declared implicitly.
  assert(ClassDecl->needsImplicitCopyConstructor());

  DeclaringSpecialMember DSM(*this, ClassDecl, CXXCopyConstructor);
  if (DSM.isAlreadyBeingDeclared())
    return nullptr;

  QualType ClassType = Context.getTypeDeclType(ClassDecl);
  QualType ArgType = ClassType;
  bool Const = ClassDecl->implicitCopyConstructorHasConstParam();
  if (Const)
    ArgType = ArgType.withConst();

  if (Context.getLangOpts().OpenCLCPlusPlus)
    ArgType = Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);

  ArgType = Context.getLValueReferenceType(ArgType);

  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
                                                     CXXCopyConstructor,
                                                     Const);

  DeclarationName Name
    = Context.DeclarationNames.getCXXConstructorName(
                                           Context.getCanonicalType(ClassType));
  SourceLocation ClassLoc = ClassDecl->getLocation();
  DeclarationNameInfo NameInfo(Name, ClassLoc);

  //   An implicitly-declared copy constructor is an inline public
  //   member of its class.
  CXXConstructorDecl *CopyConstructor = CXXConstructorDecl::Create(
      Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
      ExplicitSpecifier(),
      /*isInline=*/true,
      /*isImplicitlyDeclared=*/true, Constexpr);
  CopyConstructor->setAccess(AS_public);
  CopyConstructor->setDefaulted();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyConstructor,
                                            CopyConstructor,
                                            /* ConstRHS */ Const,
                                            /* Diagnose */ false);
  }

  setupImplicitSpecialMemberType(CopyConstructor, Context.VoidTy, ArgType);

  // Add the parameter to the constructor.
  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, CopyConstructor,
                                               ClassLoc, ClassLoc,
                                               /*IdentifierInfo=*/nullptr,
                                               ArgType, /*TInfo=*/nullptr,
                                               SC_None, nullptr);
  CopyConstructor->setParams(FromParam);

  CopyConstructor->setTrivial(
      ClassDecl->needsOverloadResolutionForCopyConstructor()
          ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor)
          : ClassDecl->hasTrivialCopyConstructor());

  CopyConstructor->setTrivialForCall(
      ClassDecl->hasAttr<TrivialABIAttr>() ||
      (ClassDecl->needsOverloadResolutionForCopyConstructor()
           ? SpecialMemberIsTrivial(CopyConstructor, CXXCopyConstructor,
             TAH_ConsiderTrivialABI)
           : ClassDecl->hasTrivialCopyConstructorForCall()));

  // Note that we have declared this constructor.
  ++getASTContext().NumImplicitCopyConstructorsDeclared;

  Scope *S = getScopeForContext(ClassDecl);
  CheckImplicitSpecialMemberDeclaration(S, CopyConstructor);

  if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor)) {
    ClassDecl->setImplicitCopyConstructorIsDeleted();
    SetDeclDeleted(CopyConstructor, ClassLoc);
  }

  if (S)
    PushOnScopeChains(CopyConstructor, S, false);
  ClassDecl->addDecl(CopyConstructor);

  return CopyConstructor;
}

void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
                                         CXXConstructorDecl *CopyConstructor) {
  assert((CopyConstructor->isDefaulted() &&
          CopyConstructor->isCopyConstructor() &&
          !CopyConstructor->doesThisDeclarationHaveABody() &&
          !CopyConstructor->isDeleted()) &&
         "DefineImplicitCopyConstructor - call it for implicit copy ctor");
  if (CopyConstructor->willHaveBody() || CopyConstructor->isInvalidDecl())
    return;

  CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
  assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");

  SynthesizedFunctionScope Scope(*this, CopyConstructor);

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       CopyConstructor->getType()->castAs<FunctionProtoType>());
  MarkVTableUsed(CurrentLocation, ClassDecl);

  // Add a context note for diagnostics produced after this point.
  Scope.addContextNote(CurrentLocation);

  // C++11 [class.copy]p7:
  //   The [definition of an implicitly declared copy constructor] is
  //   deprecated if the class has a user-declared copy assignment operator
  //   or a user-declared destructor.
  if (getLangOpts().CPlusPlus11 && CopyConstructor->isImplicit())
    diagnoseDeprecatedCopyOperation(*this, CopyConstructor);

  if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false)) {
    CopyConstructor->setInvalidDecl();
  }  else {
    SourceLocation Loc = CopyConstructor->getEndLoc().isValid()
                             ? CopyConstructor->getEndLoc()
                             : CopyConstructor->getLocation();
    Sema::CompoundScopeRAII CompoundScope(*this);
    CopyConstructor->setBody(
        ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs<Stmt>());
    CopyConstructor->markUsed(Context);
  }

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(CopyConstructor);
  }
}

CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor(
                                                    CXXRecordDecl *ClassDecl) {
  assert(ClassDecl->needsImplicitMoveConstructor());

  DeclaringSpecialMember DSM(*this, ClassDecl, CXXMoveConstructor);
  if (DSM.isAlreadyBeingDeclared())
    return nullptr;

  QualType ClassType = Context.getTypeDeclType(ClassDecl);

  QualType ArgType = ClassType;
  if (Context.getLangOpts().OpenCLCPlusPlus)
    ArgType = Context.getAddrSpaceQualType(ClassType, LangAS::opencl_generic);
  ArgType = Context.getRValueReferenceType(ArgType);

  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, ClassDecl,
                                                     CXXMoveConstructor,
                                                     false);

  DeclarationName Name
    = Context.DeclarationNames.getCXXConstructorName(
                                           Context.getCanonicalType(ClassType));
  SourceLocation ClassLoc = ClassDecl->getLocation();
  DeclarationNameInfo NameInfo(Name, ClassLoc);

  // C++11 [class.copy]p11:
  //   An implicitly-declared copy/move constructor is an inline public
  //   member of its class.
  CXXConstructorDecl *MoveConstructor = CXXConstructorDecl::Create(
      Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr,
      ExplicitSpecifier(),
      /*isInline=*/true,
      /*isImplicitlyDeclared=*/true, Constexpr);
  MoveConstructor->setAccess(AS_public);
  MoveConstructor->setDefaulted();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveConstructor,
                                            MoveConstructor,
                                            /* ConstRHS */ false,
                                            /* Diagnose */ false);
  }

  setupImplicitSpecialMemberType(MoveConstructor, Context.VoidTy, ArgType);

  // Add the parameter to the constructor.
  ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveConstructor,
                                               ClassLoc, ClassLoc,
                                               /*IdentifierInfo=*/nullptr,
                                               ArgType, /*TInfo=*/nullptr,
                                               SC_None, nullptr);
  MoveConstructor->setParams(FromParam);

  MoveConstructor->setTrivial(
      ClassDecl->needsOverloadResolutionForMoveConstructor()
          ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor)
          : ClassDecl->hasTrivialMoveConstructor());

  MoveConstructor->setTrivialForCall(
      ClassDecl->hasAttr<TrivialABIAttr>() ||
      (ClassDecl->needsOverloadResolutionForMoveConstructor()
           ? SpecialMemberIsTrivial(MoveConstructor, CXXMoveConstructor,
                                    TAH_ConsiderTrivialABI)
           : ClassDecl->hasTrivialMoveConstructorForCall()));

  // Note that we have declared this constructor.
  ++getASTContext().NumImplicitMoveConstructorsDeclared;

  Scope *S = getScopeForContext(ClassDecl);
  CheckImplicitSpecialMemberDeclaration(S, MoveConstructor);

  if (ShouldDeleteSpecialMember(MoveConstructor, CXXMoveConstructor)) {
    ClassDecl->setImplicitMoveConstructorIsDeleted();
    SetDeclDeleted(MoveConstructor, ClassLoc);
  }

  if (S)
    PushOnScopeChains(MoveConstructor, S, false);
  ClassDecl->addDecl(MoveConstructor);

  return MoveConstructor;
}

void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation,
                                         CXXConstructorDecl *MoveConstructor) {
  assert((MoveConstructor->isDefaulted() &&
          MoveConstructor->isMoveConstructor() &&
          !MoveConstructor->doesThisDeclarationHaveABody() &&
          !MoveConstructor->isDeleted()) &&
         "DefineImplicitMoveConstructor - call it for implicit move ctor");
  if (MoveConstructor->willHaveBody() || MoveConstructor->isInvalidDecl())
    return;

  CXXRecordDecl *ClassDecl = MoveConstructor->getParent();
  assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor");

  SynthesizedFunctionScope Scope(*this, MoveConstructor);

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       MoveConstructor->getType()->castAs<FunctionProtoType>());
  MarkVTableUsed(CurrentLocation, ClassDecl);

  // Add a context note for diagnostics produced after this point.
  Scope.addContextNote(CurrentLocation);

  if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false)) {
    MoveConstructor->setInvalidDecl();
  } else {
    SourceLocation Loc = MoveConstructor->getEndLoc().isValid()
                             ? MoveConstructor->getEndLoc()
                             : MoveConstructor->getLocation();
    Sema::CompoundScopeRAII CompoundScope(*this);
    MoveConstructor->setBody(ActOnCompoundStmt(
        Loc, Loc, None, /*isStmtExpr=*/ false).getAs<Stmt>());
    MoveConstructor->markUsed(Context);
  }

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(MoveConstructor);
  }
}

bool Sema::isImplicitlyDeleted(FunctionDecl *FD) {
  return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD);
}

void Sema::DefineImplicitLambdaToFunctionPointerConversion(
                            SourceLocation CurrentLocation,
                            CXXConversionDecl *Conv) {
  SynthesizedFunctionScope Scope(*this, Conv);
  assert(!Conv->getReturnType()->isUndeducedType());

  CXXRecordDecl *Lambda = Conv->getParent();
  FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
  FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();

  if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
    CallOp = InstantiateFunctionDeclaration(
        CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
    if (!CallOp)
      return;

    Invoker = InstantiateFunctionDeclaration(
        Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
    if (!Invoker)
      return;
  }

  if (CallOp->isInvalidDecl())
    return;

  // Mark the call operator referenced (and add to pending instantiations
  // if necessary).
  // For both the conversion and static-invoker template specializations
  // we construct their body's in this function, so no need to add them
  // to the PendingInstantiations.
  MarkFunctionReferenced(CurrentLocation, CallOp);

  // Fill in the __invoke function with a dummy implementation. IR generation
  // will fill in the actual details. Update its type in case it contained
  // an 'auto'.
  Invoker->markUsed(Context);
  Invoker->setReferenced();
  Invoker->setType(Conv->getReturnType()->getPointeeType());
  Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));

  // Construct the body of the conversion function { return __invoke; }.
  Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
                                       VK_LValue, Conv->getLocation()).get();
  assert(FunctionRef && "Can't refer to __invoke function?");
  Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get();
  Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(),
                                     Conv->getLocation()));
  Conv->markUsed(Context);
  Conv->setReferenced();

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Conv);
    L->CompletedImplicitDefinition(Invoker);
  }
}



void Sema::DefineImplicitLambdaToBlockPointerConversion(
       SourceLocation CurrentLocation,
       CXXConversionDecl *Conv)
{
  assert(!Conv->getParent()->isGenericLambda());

  SynthesizedFunctionScope Scope(*this, Conv);

  // Copy-initialize the lambda object as needed to capture it.
  Expr *This = ActOnCXXThis(CurrentLocation).get();
  Expr *DerefThis =CreateBuiltinUnaryOp(CurrentLocation, UO_Deref, This).get();

  ExprResult BuildBlock = BuildBlockForLambdaConversion(CurrentLocation,
                                                        Conv->getLocation(),
                                                        Conv, DerefThis);

  // If we're not under ARC, make sure we still get the _Block_copy/autorelease
  // behavior.  Note that only the general conversion function does this
  // (since it's unusable otherwise); in the case where we inline the
  // block literal, it has block literal lifetime semantics.
  if (!BuildBlock.isInvalid() && !getLangOpts().ObjCAutoRefCount)
    BuildBlock = ImplicitCastExpr::Create(Context, BuildBlock.get()->getType(),
                                          CK_CopyAndAutoreleaseBlockObject,
                                          BuildBlock.get(), nullptr, VK_RValue);

  if (BuildBlock.isInvalid()) {
    Diag(CurrentLocation, diag::note_lambda_to_block_conv);
    Conv->setInvalidDecl();
    return;
  }

  // Create the return statement that returns the block from the conversion
  // function.
  StmtResult Return = BuildReturnStmt(Conv->getLocation(), BuildBlock.get());
  if (Return.isInvalid()) {
    Diag(CurrentLocation, diag::note_lambda_to_block_conv);
    Conv->setInvalidDecl();
    return;
  }

  // Set the body of the conversion function.
  Stmt *ReturnS = Return.get();
  Conv->setBody(CompoundStmt::Create(Context, ReturnS, Conv->getLocation(),
                                     Conv->getLocation()));
  Conv->markUsed(Context);

  // We're done; notify the mutation listener, if any.
  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Conv);
  }
}

/// Determine whether the given list arguments contains exactly one
/// "real" (non-default) argument.
static bool hasOneRealArgument(MultiExprArg Args) {
  switch (Args.size()) {
  case 0:
    return false;

  default:
    if (!Args[1]->isDefaultArgument())
      return false;

    LLVM_FALLTHROUGH;
  case 1:
    return !Args[0]->isDefaultArgument();
  }

  return false;
}

ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
                            NamedDecl *FoundDecl,
                            CXXConstructorDecl *Constructor,
                            MultiExprArg ExprArgs,
                            bool HadMultipleCandidates,
                            bool IsListInitialization,
                            bool IsStdInitListInitialization,
                            bool RequiresZeroInit,
                            unsigned ConstructKind,
                            SourceRange ParenRange) {
  bool Elidable = false;

  // C++0x [class.copy]p34:
  //   When certain criteria are met, an implementation is allowed to
  //   omit the copy/move construction of a class object, even if the
  //   copy/move constructor and/or destructor for the object have
  //   side effects. [...]
  //     - when a temporary class object that has not been bound to a
  //       reference (12.2) would be copied/moved to a class object
  //       with the same cv-unqualified type, the copy/move operation
  //       can be omitted by constructing the temporary object
  //       directly into the target of the omitted copy/move
  if (ConstructKind == CXXConstructExpr::CK_Complete && Constructor &&
      Constructor->isCopyOrMoveConstructor() && hasOneRealArgument(ExprArgs)) {
    Expr *SubExpr = ExprArgs[0];
    Elidable = SubExpr->isTemporaryObject(
        Context, cast<CXXRecordDecl>(FoundDecl->getDeclContext()));
  }

  return BuildCXXConstructExpr(ConstructLoc, DeclInitType,
                               FoundDecl, Constructor,
                               Elidable, ExprArgs, HadMultipleCandidates,
                               IsListInitialization,
                               IsStdInitListInitialization, RequiresZeroInit,
                               ConstructKind, ParenRange);
}

ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
                            NamedDecl *FoundDecl,
                            CXXConstructorDecl *Constructor,
                            bool Elidable,
                            MultiExprArg ExprArgs,
                            bool HadMultipleCandidates,
                            bool IsListInitialization,
                            bool IsStdInitListInitialization,
                            bool RequiresZeroInit,
                            unsigned ConstructKind,
                            SourceRange ParenRange) {
  if (auto *Shadow = dyn_cast<ConstructorUsingShadowDecl>(FoundDecl)) {
    Constructor = findInheritingConstructor(ConstructLoc, Constructor, Shadow);
    if (DiagnoseUseOfDecl(Constructor, ConstructLoc))
      return ExprError();
  }

  return BuildCXXConstructExpr(
      ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs,
      HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization,
      RequiresZeroInit, ConstructKind, ParenRange);
}

/// BuildCXXConstructExpr - Creates a complete call to a constructor,
/// including handling of its default argument expressions.
ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
                            CXXConstructorDecl *Constructor,
                            bool Elidable,
                            MultiExprArg ExprArgs,
                            bool HadMultipleCandidates,
                            bool IsListInitialization,
                            bool IsStdInitListInitialization,
                            bool RequiresZeroInit,
                            unsigned ConstructKind,
                            SourceRange ParenRange) {
  assert(declaresSameEntity(
             Constructor->getParent(),
             DeclInitType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) &&
         "given constructor for wrong type");
  MarkFunctionReferenced(ConstructLoc, Constructor);
  if (getLangOpts().CUDA && !CheckCUDACall(ConstructLoc, Constructor))
    return ExprError();

  return CXXConstructExpr::Create(
      Context, DeclInitType, ConstructLoc, Constructor, Elidable,
      ExprArgs, HadMultipleCandidates, IsListInitialization,
      IsStdInitListInitialization, RequiresZeroInit,
      static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
      ParenRange);
}

ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) {
  assert(Field->hasInClassInitializer());

  // If we already have the in-class initializer nothing needs to be done.
  if (Field->getInClassInitializer())
    return CXXDefaultInitExpr::Create(Context, Loc, Field, CurContext);

  // If we might have already tried and failed to instantiate, don't try again.
  if (Field->isInvalidDecl())
    return ExprError();

  // Maybe we haven't instantiated the in-class initializer. Go check the
  // pattern FieldDecl to see if it has one.
  CXXRecordDecl *ParentRD = cast<CXXRecordDecl>(Field->getParent());

  if (isTemplateInstantiation(ParentRD->getTemplateSpecializationKind())) {
    CXXRecordDecl *ClassPattern = ParentRD->getTemplateInstantiationPattern();
    DeclContext::lookup_result Lookup =
        ClassPattern->lookup(Field->getDeclName());

    // Lookup can return at most two results: the pattern for the field, or the
    // injected class name of the parent record. No other member can have the
    // same name as the field.
    // In modules mode, lookup can return multiple results (coming from
    // different modules).
    assert((getLangOpts().Modules || (!Lookup.empty() && Lookup.size() <= 2)) &&
           "more than two lookup results for field name");
    FieldDecl *Pattern = dyn_cast<FieldDecl>(Lookup[0]);
    if (!Pattern) {
      assert(isa<CXXRecordDecl>(Lookup[0]) &&
             "cannot have other non-field member with same name");
      for (auto L : Lookup)
        if (isa<FieldDecl>(L)) {
          Pattern = cast<FieldDecl>(L);
          break;
        }
      assert(Pattern && "We must have set the Pattern!");
    }

    if (!Pattern->hasInClassInitializer() ||
        InstantiateInClassInitializer(Loc, Field, Pattern,
                                      getTemplateInstantiationArgs(Field))) {
      // Don't diagnose this again.
      Field->setInvalidDecl();
      return ExprError();
    }
    return CXXDefaultInitExpr::Create(Context, Loc, Field, CurContext);
  }

  // DR1351:
  //   If the brace-or-equal-initializer of a non-static data member
  //   invokes a defaulted default constructor of its class or of an
  //   enclosing class in a potentially evaluated subexpression, the
  //   program is ill-formed.
  //
  // This resolution is unworkable: the exception specification of the
  // default constructor can be needed in an unevaluated context, in
  // particular, in the operand of a noexcept-expression, and we can be
  // unable to compute an exception specification for an enclosed class.
  //
  // Any attempt to resolve the exception specification of a defaulted default
  // constructor before the initializer is lexically complete will ultimately
  // come here at which point we can diagnose it.
  RecordDecl *OutermostClass = ParentRD->getOuterLexicalRecordContext();
  Diag(Loc, diag::err_in_class_initializer_not_yet_parsed)
      << OutermostClass << Field;
  Diag(Field->getEndLoc(), diag::note_in_class_initializer_not_yet_parsed);
  // Recover by marking the field invalid, unless we're in a SFINAE context.
  if (!isSFINAEContext())
    Field->setInvalidDecl();
  return ExprError();
}

void Sema::FinalizeVarWithDestructor(VarDecl *VD, const RecordType *Record) {
  if (VD->isInvalidDecl()) return;

  CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Record->getDecl());
  if (ClassDecl->isInvalidDecl()) return;
  if (ClassDecl->hasIrrelevantDestructor()) return;
  if (ClassDecl->isDependentContext()) return;

  if (VD->isNoDestroy(getASTContext()))
    return;

  CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);

  // If this is an array, we'll require the destructor during initialization, so
  // we can skip over this. We still want to emit exit-time destructor warnings
  // though.
  if (!VD->getType()->isArrayType()) {
    MarkFunctionReferenced(VD->getLocation(), Destructor);
    CheckDestructorAccess(VD->getLocation(), Destructor,
                          PDiag(diag::err_access_dtor_var)
                              << VD->getDeclName() << VD->getType());
    DiagnoseUseOfDecl(Destructor, VD->getLocation());
  }

  if (Destructor->isTrivial()) return;
  if (!VD->hasGlobalStorage()) return;

  // Emit warning for non-trivial dtor in global scope (a real global,
  // class-static, function-static).
  Diag(VD->getLocation(), diag::warn_exit_time_destructor);

  // TODO: this should be re-enabled for static locals by !CXAAtExit
  if (!VD->isStaticLocal())
    Diag(VD->getLocation(), diag::warn_global_destructor);
}

/// Given a constructor and the set of arguments provided for the
/// constructor, convert the arguments and add any required default arguments
/// to form a proper call to this constructor.
///
/// \returns true if an error occurred, false otherwise.
bool
Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
                              MultiExprArg ArgsPtr,
                              SourceLocation Loc,
                              SmallVectorImpl<Expr*> &ConvertedArgs,
                              bool AllowExplicit,
                              bool IsListInitialization) {
  // FIXME: This duplicates a lot of code from Sema::ConvertArgumentsForCall.
  unsigned NumArgs = ArgsPtr.size();
  Expr **Args = ArgsPtr.data();

  const FunctionProtoType *Proto
    = Constructor->getType()->getAs<FunctionProtoType>();
  assert(Proto && "Constructor without a prototype?");
  unsigned NumParams = Proto->getNumParams();

  // If too few arguments are available, we'll fill in the rest with defaults.
  if (NumArgs < NumParams)
    ConvertedArgs.reserve(NumParams);
  else
    ConvertedArgs.reserve(NumArgs);

  VariadicCallType CallType =
    Proto->isVariadic() ? VariadicConstructor : VariadicDoesNotApply;
  SmallVector<Expr *, 8> AllArgs;
  bool Invalid = GatherArgumentsForCall(Loc, Constructor,
                                        Proto, 0,
                                        llvm::makeArrayRef(Args, NumArgs),
                                        AllArgs,
                                        CallType, AllowExplicit,
                                        IsListInitialization);
  ConvertedArgs.append(AllArgs.begin(), AllArgs.end());

  DiagnoseSentinelCalls(Constructor, Loc, AllArgs);

  CheckConstructorCall(Constructor,
                       llvm::makeArrayRef(AllArgs.data(), AllArgs.size()),
                       Proto, Loc);

  return Invalid;
}

static inline bool
CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef,
                                       const FunctionDecl *FnDecl) {
  const DeclContext *DC = FnDecl->getDeclContext()->getRedeclContext();
  if (isa<NamespaceDecl>(DC)) {
    return SemaRef.Diag(FnDecl->getLocation(),
                        diag::err_operator_new_delete_declared_in_namespace)
      << FnDecl->getDeclName();
  }

  if (isa<TranslationUnitDecl>(DC) &&
      FnDecl->getStorageClass() == SC_Static) {
    return SemaRef.Diag(FnDecl->getLocation(),
                        diag::err_operator_new_delete_declared_static)
      << FnDecl->getDeclName();
  }

  return false;
}

static QualType
RemoveAddressSpaceFromPtr(Sema &SemaRef, const PointerType *PtrTy) {
  QualType QTy = PtrTy->getPointeeType();
  QTy = SemaRef.Context.removeAddrSpaceQualType(QTy);
  return SemaRef.Context.getPointerType(QTy);
}

static inline bool
CheckOperatorNewDeleteTypes(Sema &SemaRef, const FunctionDecl *FnDecl,
                            CanQualType ExpectedResultType,
                            CanQualType ExpectedFirstParamType,
                            unsigned DependentParamTypeDiag,
                            unsigned InvalidParamTypeDiag) {
  QualType ResultType =
      FnDecl->getType()->getAs<FunctionType>()->getReturnType();

  // Check that the result type is not dependent.
  if (ResultType->isDependentType())
    return SemaRef.Diag(FnDecl->getLocation(),
                        diag::err_operator_new_delete_dependent_result_type)
    << FnDecl->getDeclName() << ExpectedResultType;

  // OpenCL C++: the operator is valid on any address space.
  if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
    if (auto *PtrTy = ResultType->getAs<PointerType>()) {
      ResultType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
    }
  }

  // Check that the result type is what we expect.
  if (SemaRef.Context.getCanonicalType(ResultType) != ExpectedResultType)
    return SemaRef.Diag(FnDecl->getLocation(),
                        diag::err_operator_new_delete_invalid_result_type)
    << FnDecl->getDeclName() << ExpectedResultType;

  // A function template must have at least 2 parameters.
  if (FnDecl->getDescribedFunctionTemplate() && FnDecl->getNumParams() < 2)
    return SemaRef.Diag(FnDecl->getLocation(),
                      diag::err_operator_new_delete_template_too_few_parameters)
        << FnDecl->getDeclName();

  // The function decl must have at least 1 parameter.
  if (FnDecl->getNumParams() == 0)
    return SemaRef.Diag(FnDecl->getLocation(),
                        diag::err_operator_new_delete_too_few_parameters)
      << FnDecl->getDeclName();

  // Check the first parameter type is not dependent.
  QualType FirstParamType = FnDecl->getParamDecl(0)->getType();
  if (FirstParamType->isDependentType())
    return SemaRef.Diag(FnDecl->getLocation(), DependentParamTypeDiag)
      << FnDecl->getDeclName() << ExpectedFirstParamType;

  // Check that the first parameter type is what we expect.
  if (SemaRef.getLangOpts().OpenCLCPlusPlus) {
    // OpenCL C++: the operator is valid on any address space.
    if (auto *PtrTy =
            FnDecl->getParamDecl(0)->getType()->getAs<PointerType>()) {
      FirstParamType = RemoveAddressSpaceFromPtr(SemaRef, PtrTy);
    }
  }
  if (SemaRef.Context.getCanonicalType(FirstParamType).getUnqualifiedType() !=
      ExpectedFirstParamType)
    return SemaRef.Diag(FnDecl->getLocation(), InvalidParamTypeDiag)
    << FnDecl->getDeclName() << ExpectedFirstParamType;

  return false;
}

static bool
CheckOperatorNewDeclaration(Sema &SemaRef, const FunctionDecl *FnDecl) {
  // C++ [basic.stc.dynamic.allocation]p1:
  //   A program is ill-formed if an allocation function is declared in a
  //   namespace scope other than global scope or declared static in global
  //   scope.
  if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
    return true;

  CanQualType SizeTy =
    SemaRef.Context.getCanonicalType(SemaRef.Context.getSizeType());

  // C++ [basic.stc.dynamic.allocation]p1:
  //  The return type shall be void*. The first parameter shall have type
  //  std::size_t.
  if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidPtrTy,
                                  SizeTy,
                                  diag::err_operator_new_dependent_param_type,
                                  diag::err_operator_new_param_type))
    return true;

  // C++ [basic.stc.dynamic.allocation]p1:
  //  The first parameter shall not have an associated default argument.
  if (FnDecl->getParamDecl(0)->hasDefaultArg())
    return SemaRef.Diag(FnDecl->getLocation(),
                        diag::err_operator_new_default_arg)
      << FnDecl->getDeclName() << FnDecl->getParamDecl(0)->getDefaultArgRange();

  return false;
}

static bool
CheckOperatorDeleteDeclaration(Sema &SemaRef, FunctionDecl *FnDecl) {
  // C++ [basic.stc.dynamic.deallocation]p1:
  //   A program is ill-formed if deallocation functions are declared in a
  //   namespace scope other than global scope or declared static in global
  //   scope.
  if (CheckOperatorNewDeleteDeclarationScope(SemaRef, FnDecl))
    return true;

  auto *MD = dyn_cast<CXXMethodDecl>(FnDecl);

  // C++ P0722:
  //   Within a class C, the first parameter of a destroying operator delete
  //   shall be of type C *. The first parameter of any other deallocation
  //   function shall be of type void *.
  CanQualType ExpectedFirstParamType =
      MD && MD->isDestroyingOperatorDelete()
          ? SemaRef.Context.getCanonicalType(SemaRef.Context.getPointerType(
                SemaRef.Context.getRecordType(MD->getParent())))
          : SemaRef.Context.VoidPtrTy;

  // C++ [basic.stc.dynamic.deallocation]p2:
  //   Each deallocation function shall return void
  if (CheckOperatorNewDeleteTypes(
          SemaRef, FnDecl, SemaRef.Context.VoidTy, ExpectedFirstParamType,
          diag::err_operator_delete_dependent_param_type,
          diag::err_operator_delete_param_type))
    return true;

  // C++ P0722:
  //   A destroying operator delete shall be a usual deallocation function.
  if (MD && !MD->getParent()->isDependentContext() &&
      MD->isDestroyingOperatorDelete() &&
      !SemaRef.isUsualDeallocationFunction(MD)) {
    SemaRef.Diag(MD->getLocation(),
                 diag::err_destroying_operator_delete_not_usual);
    return true;
  }

  return false;
}

/// CheckOverloadedOperatorDeclaration - Check whether the declaration
/// of this overloaded operator is well-formed. If so, returns false;
/// otherwise, emits appropriate diagnostics and returns true.
bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
  assert(FnDecl && FnDecl->isOverloadedOperator() &&
         "Expected an overloaded operator declaration");

  OverloadedOperatorKind Op = FnDecl->getOverloadedOperator();

  // C++ [over.oper]p5:
  //   The allocation and deallocation functions, operator new,
  //   operator new[], operator delete and operator delete[], are
  //   described completely in 3.7.3. The attributes and restrictions
  //   found in the rest of this subclause do not apply to them unless
  //   explicitly stated in 3.7.3.
  if (Op == OO_Delete || Op == OO_Array_Delete)
    return CheckOperatorDeleteDeclaration(*this, FnDecl);

  if (Op == OO_New || Op == OO_Array_New)
    return CheckOperatorNewDeclaration(*this, FnDecl);

  // C++ [over.oper]p6:
  //   An operator function shall either be a non-static member
  //   function or be a non-member function and have at least one
  //   parameter whose type is a class, a reference to a class, an
  //   enumeration, or a reference to an enumeration.
  if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
    if (MethodDecl->isStatic())
      return Diag(FnDecl->getLocation(),
                  diag::err_operator_overload_static) << FnDecl->getDeclName();
  } else {
    bool ClassOrEnumParam = false;
    for (auto Param : FnDecl->parameters()) {
      QualType ParamType = Param->getType().getNonReferenceType();
      if (ParamType->isDependentType() || ParamType->isRecordType() ||
          ParamType->isEnumeralType()) {
        ClassOrEnumParam = true;
        break;
      }
    }

    if (!ClassOrEnumParam)
      return Diag(FnDecl->getLocation(),
                  diag::err_operator_overload_needs_class_or_enum)
        << FnDecl->getDeclName();
  }

  // C++ [over.oper]p8:
  //   An operator function cannot have default arguments (8.3.6),
  //   except where explicitly stated below.
  //
  // Only the function-call operator allows default arguments
  // (C++ [over.call]p1).
  if (Op != OO_Call) {
    for (auto Param : FnDecl->parameters()) {
      if (Param->hasDefaultArg())
        return Diag(Param->getLocation(),
                    diag::err_operator_overload_default_arg)
          << FnDecl->getDeclName() << Param->getDefaultArgRange();
    }
  }

  static const bool OperatorUses[NUM_OVERLOADED_OPERATORS][3] = {
    { false, false, false }
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
    , { Unary, Binary, MemberOnly }
#include "clang/Basic/OperatorKinds.def"
  };

  bool CanBeUnaryOperator = OperatorUses[Op][0];
  bool CanBeBinaryOperator = OperatorUses[Op][1];
  bool MustBeMemberOperator = OperatorUses[Op][2];

  // C++ [over.oper]p8:
  //   [...] Operator functions cannot have more or fewer parameters
  //   than the number required for the corresponding operator, as
  //   described in the rest of this subclause.
  unsigned NumParams = FnDecl->getNumParams()
                     + (isa<CXXMethodDecl>(FnDecl)? 1 : 0);
  if (Op != OO_Call &&
      ((NumParams == 1 && !CanBeUnaryOperator) ||
       (NumParams == 2 && !CanBeBinaryOperator) ||
       (NumParams < 1) || (NumParams > 2))) {
    // We have the wrong number of parameters.
    unsigned ErrorKind;
    if (CanBeUnaryOperator && CanBeBinaryOperator) {
      ErrorKind = 2;  // 2 -> unary or binary.
    } else if (CanBeUnaryOperator) {
      ErrorKind = 0;  // 0 -> unary
    } else {
      assert(CanBeBinaryOperator &&
             "All non-call overloaded operators are unary or binary!");
      ErrorKind = 1;  // 1 -> binary
    }

    return Diag(FnDecl->getLocation(), diag::err_operator_overload_must_be)
      << FnDecl->getDeclName() << NumParams << ErrorKind;
  }

  // Overloaded operators other than operator() cannot be variadic.
  if (Op != OO_Call &&
      FnDecl->getType()->getAs<FunctionProtoType>()->isVariadic()) {
    return Diag(FnDecl->getLocation(), diag::err_operator_overload_variadic)
      << FnDecl->getDeclName();
  }

  // Some operators must be non-static member functions.
  if (MustBeMemberOperator && !isa<CXXMethodDecl>(FnDecl)) {
    return Diag(FnDecl->getLocation(),
                diag::err_operator_overload_must_be_member)
      << FnDecl->getDeclName();
  }

  // C++ [over.inc]p1:
  //   The user-defined function called operator++ implements the
  //   prefix and postfix ++ operator. If this function is a member
  //   function with no parameters, or a non-member function with one
  //   parameter of class or enumeration type, it defines the prefix
  //   increment operator ++ for objects of that type. If the function
  //   is a member function with one parameter (which shall be of type
  //   int) or a non-member function with two parameters (the second
  //   of which shall be of type int), it defines the postfix
  //   increment operator ++ for objects of that type.
  if ((Op == OO_PlusPlus || Op == OO_MinusMinus) && NumParams == 2) {
    ParmVarDecl *LastParam = FnDecl->getParamDecl(FnDecl->getNumParams() - 1);
    QualType ParamType = LastParam->getType();

    if (!ParamType->isSpecificBuiltinType(BuiltinType::Int) &&
        !ParamType->isDependentType())
      return Diag(LastParam->getLocation(),
                  diag::err_operator_overload_post_incdec_must_be_int)
        << LastParam->getType() << (Op == OO_MinusMinus);
  }

  return false;
}

static bool
checkLiteralOperatorTemplateParameterList(Sema &SemaRef,
                                          FunctionTemplateDecl *TpDecl) {
  TemplateParameterList *TemplateParams = TpDecl->getTemplateParameters();

  // Must have one or two template parameters.
  if (TemplateParams->size() == 1) {
    NonTypeTemplateParmDecl *PmDecl =
        dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(0));

    // The template parameter must be a char parameter pack.
    if (PmDecl && PmDecl->isTemplateParameterPack() &&
        SemaRef.Context.hasSameType(PmDecl->getType(), SemaRef.Context.CharTy))
      return false;

  } else if (TemplateParams->size() == 2) {
    TemplateTypeParmDecl *PmType =
        dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(0));
    NonTypeTemplateParmDecl *PmArgs =
        dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(1));

    // The second template parameter must be a parameter pack with the
    // first template parameter as its type.
    if (PmType && PmArgs && !PmType->isTemplateParameterPack() &&
        PmArgs->isTemplateParameterPack()) {
      const TemplateTypeParmType *TArgs =
          PmArgs->getType()->getAs<TemplateTypeParmType>();
      if (TArgs && TArgs->getDepth() == PmType->getDepth() &&
          TArgs->getIndex() == PmType->getIndex()) {
        if (!SemaRef.inTemplateInstantiation())
          SemaRef.Diag(TpDecl->getLocation(),
                       diag::ext_string_literal_operator_template);
        return false;
      }
    }
  }

  SemaRef.Diag(TpDecl->getTemplateParameters()->getSourceRange().getBegin(),
               diag::err_literal_operator_template)
      << TpDecl->getTemplateParameters()->getSourceRange();
  return true;
}

/// CheckLiteralOperatorDeclaration - Check whether the declaration
/// of this literal operator function is well-formed. If so, returns
/// false; otherwise, emits appropriate diagnostics and returns true.
bool Sema::CheckLiteralOperatorDeclaration(FunctionDecl *FnDecl) {
  if (isa<CXXMethodDecl>(FnDecl)) {
    Diag(FnDecl->getLocation(), diag::err_literal_operator_outside_namespace)
      << FnDecl->getDeclName();
    return true;
  }

  if (FnDecl->isExternC()) {
    Diag(FnDecl->getLocation(), diag::err_literal_operator_extern_c);
    if (const LinkageSpecDecl *LSD =
            FnDecl->getDeclContext()->getExternCContext())
      Diag(LSD->getExternLoc(), diag::note_extern_c_begins_here);
    return true;
  }

  // This might be the definition of a literal operator template.
  FunctionTemplateDecl *TpDecl = FnDecl->getDescribedFunctionTemplate();

  // This might be a specialization of a literal operator template.
  if (!TpDecl)
    TpDecl = FnDecl->getPrimaryTemplate();

  // template <char...> type operator "" name() and
  // template <class T, T...> type operator "" name() are the only valid
  // template signatures, and the only valid signatures with no parameters.
  if (TpDecl) {
    if (FnDecl->param_size() != 0) {
      Diag(FnDecl->getLocation(),
           diag::err_literal_operator_template_with_params);
      return true;
    }

    if (checkLiteralOperatorTemplateParameterList(*this, TpDecl))
      return true;

  } else if (FnDecl->param_size() == 1) {
    const ParmVarDecl *Param = FnDecl->getParamDecl(0);

    QualType ParamType = Param->getType().getUnqualifiedType();

    // Only unsigned long long int, long double, any character type, and const
    // char * are allowed as the only parameters.
    if (ParamType->isSpecificBuiltinType(BuiltinType::ULongLong) ||
        ParamType->isSpecificBuiltinType(BuiltinType::LongDouble) ||
        Context.hasSameType(ParamType, Context.CharTy) ||
        Context.hasSameType(ParamType, Context.WideCharTy) ||
        Context.hasSameType(ParamType, Context.Char8Ty) ||
        Context.hasSameType(ParamType, Context.Char16Ty) ||
        Context.hasSameType(ParamType, Context.Char32Ty)) {
    } else if (const PointerType *Ptr = ParamType->getAs<PointerType>()) {
      QualType InnerType = Ptr->getPointeeType();

      // Pointer parameter must be a const char *.
      if (!(Context.hasSameType(InnerType.getUnqualifiedType(),
                                Context.CharTy) &&
            InnerType.isConstQualified() && !InnerType.isVolatileQualified())) {
        Diag(Param->getSourceRange().getBegin(),
             diag::err_literal_operator_param)
            << ParamType << "'const char *'" << Param->getSourceRange();
        return true;
      }

    } else if (ParamType->isRealFloatingType()) {
      Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param)
          << ParamType << Context.LongDoubleTy << Param->getSourceRange();
      return true;

    } else if (ParamType->isIntegerType()) {
      Diag(Param->getSourceRange().getBegin(), diag::err_literal_operator_param)
          << ParamType << Context.UnsignedLongLongTy << Param->getSourceRange();
      return true;

    } else {
      Diag(Param->getSourceRange().getBegin(),
           diag::err_literal_operator_invalid_param)
          << ParamType << Param->getSourceRange();
      return true;
    }

  } else if (FnDecl->param_size() == 2) {
    FunctionDecl::param_iterator Param = FnDecl->param_begin();

    // First, verify that the first parameter is correct.

    QualType FirstParamType = (*Param)->getType().getUnqualifiedType();

    // Two parameter function must have a pointer to const as a
    // first parameter; let's strip those qualifiers.
    const PointerType *PT = FirstParamType->getAs<PointerType>();

    if (!PT) {
      Diag((*Param)->getSourceRange().getBegin(),
           diag::err_literal_operator_param)
          << FirstParamType << "'const char *'" << (*Param)->getSourceRange();
      return true;
    }

    QualType PointeeType = PT->getPointeeType();
    // First parameter must be const
    if (!PointeeType.isConstQualified() || PointeeType.isVolatileQualified()) {
      Diag((*Param)->getSourceRange().getBegin(),
           diag::err_literal_operator_param)
          << FirstParamType << "'const char *'" << (*Param)->getSourceRange();
      return true;
    }

    QualType InnerType = PointeeType.getUnqualifiedType();
    // Only const char *, const wchar_t*, const char8_t*, const char16_t*, and
    // const char32_t* are allowed as the first parameter to a two-parameter
    // function
    if (!(Context.hasSameType(InnerType, Context.CharTy) ||
          Context.hasSameType(InnerType, Context.WideCharTy) ||
          Context.hasSameType(InnerType, Context.Char8Ty) ||
          Context.hasSameType(InnerType, Context.Char16Ty) ||
          Context.hasSameType(InnerType, Context.Char32Ty))) {
      Diag((*Param)->getSourceRange().getBegin(),
           diag::err_literal_operator_param)
          << FirstParamType << "'const char *'" << (*Param)->getSourceRange();
      return true;
    }

    // Move on to the second and final parameter.
    ++Param;

    // The second parameter must be a std::size_t.
    QualType SecondParamType = (*Param)->getType().getUnqualifiedType();
    if (!Context.hasSameType(SecondParamType, Context.getSizeType())) {
      Diag((*Param)->getSourceRange().getBegin(),
           diag::err_literal_operator_param)
          << SecondParamType << Context.getSizeType()
          << (*Param)->getSourceRange();
      return true;
    }
  } else {
    Diag(FnDecl->getLocation(), diag::err_literal_operator_bad_param_count);
    return true;
  }

  // Parameters are good.

  // A parameter-declaration-clause containing a default argument is not
  // equivalent to any of the permitted forms.
  for (auto Param : FnDecl->parameters()) {
    if (Param->hasDefaultArg()) {
      Diag(Param->getDefaultArgRange().getBegin(),
           diag::err_literal_operator_default_argument)
        << Param->getDefaultArgRange();
      break;
    }
  }

  StringRef LiteralName
    = FnDecl->getDeclName().getCXXLiteralIdentifier()->getName();
  if (LiteralName[0] != '_' &&
      !getSourceManager().isInSystemHeader(FnDecl->getLocation())) {
    // C++11 [usrlit.suffix]p1:
    //   Literal suffix identifiers that do not start with an underscore
    //   are reserved for future standardization.
    Diag(FnDecl->getLocation(), diag::warn_user_literal_reserved)
      << StringLiteralParser::isValidUDSuffix(getLangOpts(), LiteralName);
  }

  return false;
}

/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
/// linkage specification, including the language and (if present)
/// the '{'. ExternLoc is the location of the 'extern', Lang is the
/// language string literal. LBraceLoc, if valid, provides the location of
/// the '{' brace. Otherwise, this linkage specification does not
/// have any braces.
Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,
                                           Expr *LangStr,
                                           SourceLocation LBraceLoc) {
  StringLiteral *Lit = cast<StringLiteral>(LangStr);
  if (!Lit->isAscii()) {
    Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_not_ascii)
      << LangStr->getSourceRange();
    return nullptr;
  }

  StringRef Lang = Lit->getString();
  LinkageSpecDecl::LanguageIDs Language;
  if (Lang == "C")
    Language = LinkageSpecDecl::lang_c;
  else if (Lang == "C++")
    Language = LinkageSpecDecl::lang_cxx;
  else {
    Diag(LangStr->getExprLoc(), diag::err_language_linkage_spec_unknown)
      << LangStr->getSourceRange();
    return nullptr;
  }

  // FIXME: Add all the various semantics of linkage specifications

  LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, ExternLoc,
                                               LangStr->getExprLoc(), Language,
                                               LBraceLoc.isValid());
  CurContext->addDecl(D);
  PushDeclContext(S, D);
  return D;
}

/// ActOnFinishLinkageSpecification - Complete the definition of
/// the C++ linkage specification LinkageSpec. If RBraceLoc is
/// valid, it's the position of the closing '}' brace in a linkage
/// specification that uses braces.
Decl *Sema::ActOnFinishLinkageSpecification(Scope *S,
                                            Decl *LinkageSpec,
                                            SourceLocation RBraceLoc) {
  if (RBraceLoc.isValid()) {
    LinkageSpecDecl* LSDecl = cast<LinkageSpecDecl>(LinkageSpec);
    LSDecl->setRBraceLoc(RBraceLoc);
  }
  PopDeclContext();
  return LinkageSpec;
}

Decl *Sema::ActOnEmptyDeclaration(Scope *S,
                                  const ParsedAttributesView &AttrList,
                                  SourceLocation SemiLoc) {
  Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc);
  // Attribute declarations appertain to empty declaration so we handle
  // them here.
  ProcessDeclAttributeList(S, ED, AttrList);

  CurContext->addDecl(ED);
  return ED;
}

/// Perform semantic analysis for the variable declaration that
/// occurs within a C++ catch clause, returning the newly-created
/// variable.
VarDecl *Sema::BuildExceptionDeclaration(Scope *S,
                                         TypeSourceInfo *TInfo,
                                         SourceLocation StartLoc,
                                         SourceLocation Loc,
                                         IdentifierInfo *Name) {
  bool Invalid = false;
  QualType ExDeclType = TInfo->getType();

  // Arrays and functions decay.
  if (ExDeclType->isArrayType())
    ExDeclType = Context.getArrayDecayedType(ExDeclType);
  else if (ExDeclType->isFunctionType())
    ExDeclType = Context.getPointerType(ExDeclType);

  // C++ 15.3p1: The exception-declaration shall not denote an incomplete type.
  // The exception-declaration shall not denote a pointer or reference to an
  // incomplete type, other than [cv] void*.
  // N2844 forbids rvalue references.
  if (!ExDeclType->isDependentType() && ExDeclType->isRValueReferenceType()) {
    Diag(Loc, diag::err_catch_rvalue_ref);
    Invalid = true;
  }

  if (ExDeclType->isVariablyModifiedType()) {
    Diag(Loc, diag::err_catch_variably_modified) << ExDeclType;
    Invalid = true;
  }

  QualType BaseType = ExDeclType;
  int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
  unsigned DK = diag::err_catch_incomplete;
  if (const PointerType *Ptr = BaseType->getAs<PointerType>()) {
    BaseType = Ptr->getPointeeType();
    Mode = 1;
    DK = diag::err_catch_incomplete_ptr;
  } else if (const ReferenceType *Ref = BaseType->getAs<ReferenceType>()) {
    // For the purpose of error recovery, we treat rvalue refs like lvalue refs.
    BaseType = Ref->getPointeeType();
    Mode = 2;
    DK = diag::err_catch_incomplete_ref;
  }
  if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) &&
      !BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK))
    Invalid = true;

  if (!Invalid && !ExDeclType->isDependentType() &&
      RequireNonAbstractType(Loc, ExDeclType,
                             diag::err_abstract_type_in_decl,
                             AbstractVariableType))
    Invalid = true;

  // Only the non-fragile NeXT runtime currently supports C++ catches
  // of ObjC types, and no runtime supports catching ObjC types by value.
  if (!Invalid && getLangOpts().ObjC) {
    QualType T = ExDeclType;
    if (const ReferenceType *RT = T->getAs<ReferenceType>())
      T = RT->getPointeeType();

    if (T->isObjCObjectType()) {
      Diag(Loc, diag::err_objc_object_catch);
      Invalid = true;
    } else if (T->isObjCObjectPointerType()) {
      // FIXME: should this be a test for macosx-fragile specifically?
      if (getLangOpts().ObjCRuntime.isFragile())
        Diag(Loc, diag::warn_objc_pointer_cxx_catch_fragile);
    }
  }

  VarDecl *ExDecl = VarDecl::Create(Context, CurContext, StartLoc, Loc, Name,
                                    ExDeclType, TInfo, SC_None);
  ExDecl->setExceptionVariable(true);

  // In ARC, infer 'retaining' for variables of retainable type.
  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(ExDecl))
    Invalid = true;

  if (!Invalid && !ExDeclType->isDependentType()) {
    if (const RecordType *recordType = ExDeclType->getAs<RecordType>()) {
      // Insulate this from anything else we might currently be parsing.
      EnterExpressionEvaluationContext scope(
          *this, ExpressionEvaluationContext::PotentiallyEvaluated);

      // C++ [except.handle]p16:
      //   The object declared in an exception-declaration or, if the
      //   exception-declaration does not specify a name, a temporary (12.2) is
      //   copy-initialized (8.5) from the exception object. [...]
      //   The object is destroyed when the handler exits, after the destruction
      //   of any automatic objects initialized within the handler.
      //
      // We just pretend to initialize the object with itself, then make sure
      // it can be destroyed later.
      QualType initType = Context.getExceptionObjectType(ExDeclType);

      InitializedEntity entity =
        InitializedEntity::InitializeVariable(ExDecl);
      InitializationKind initKind =
        InitializationKind::CreateCopy(Loc, SourceLocation());

      Expr *opaqueValue =
        new (Context) OpaqueValueExpr(Loc, initType, VK_LValue, OK_Ordinary);
      InitializationSequence sequence(*this, entity, initKind, opaqueValue);
      ExprResult result = sequence.Perform(*this, entity, initKind, opaqueValue);
      if (result.isInvalid())
        Invalid = true;
      else {
        // If the constructor used was non-trivial, set this as the
        // "initializer".
        CXXConstructExpr *construct = result.getAs<CXXConstructExpr>();
        if (!construct->getConstructor()->isTrivial()) {
          Expr *init = MaybeCreateExprWithCleanups(construct);
          ExDecl->setInit(init);
        }

        // And make sure it's destructable.
        FinalizeVarWithDestructor(ExDecl, recordType);
      }
    }
  }

  if (Invalid)
    ExDecl->setInvalidDecl();

  return ExDecl;
}

/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
/// handler.
Decl *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
  bool Invalid = D.isInvalidType();

  // Check for unexpanded parameter packs.
  if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
                                      UPPC_ExceptionType)) {
    TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
                                             D.getIdentifierLoc());
    Invalid = true;
  }

  IdentifierInfo *II = D.getIdentifier();
  if (NamedDecl *PrevDecl = LookupSingleName(S, II, D.getIdentifierLoc(),
                                             LookupOrdinaryName,
                                             ForVisibleRedeclaration)) {
    // The scope should be freshly made just for us. There is just no way
    // it contains any previous declaration, except for function parameters in
    // a function-try-block's catch statement.
    assert(!S->isDeclScope(PrevDecl));
    if (isDeclInScope(PrevDecl, CurContext, S)) {
      Diag(D.getIdentifierLoc(), diag::err_redefinition)
        << D.getIdentifier();
      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
      Invalid = true;
    } else if (PrevDecl->isTemplateParameter())
      // Maybe we will complain about the shadowed template parameter.
      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
  }

  if (D.getCXXScopeSpec().isSet() && !Invalid) {
    Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
      << D.getCXXScopeSpec().getRange();
    Invalid = true;
  }

  VarDecl *ExDecl = BuildExceptionDeclaration(
      S, TInfo, D.getBeginLoc(), D.getIdentifierLoc(), D.getIdentifier());
  if (Invalid)
    ExDecl->setInvalidDecl();

  // Add the exception declaration into this scope.
  if (II)
    PushOnScopeChains(ExDecl, S);
  else
    CurContext->addDecl(ExDecl);

  ProcessDeclAttributes(S, ExDecl, D);
  return ExDecl;
}

Decl *Sema::ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc,
                                         Expr *AssertExpr,
                                         Expr *AssertMessageExpr,
                                         SourceLocation RParenLoc) {
  StringLiteral *AssertMessage =
      AssertMessageExpr ? cast<StringLiteral>(AssertMessageExpr) : nullptr;

  if (DiagnoseUnexpandedParameterPack(AssertExpr, UPPC_StaticAssertExpression))
    return nullptr;

  return BuildStaticAssertDeclaration(StaticAssertLoc, AssertExpr,
                                      AssertMessage, RParenLoc, false);
}

Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
                                         Expr *AssertExpr,
                                         StringLiteral *AssertMessage,
                                         SourceLocation RParenLoc,
                                         bool Failed) {
  assert(AssertExpr != nullptr && "Expected non-null condition");
  if (!AssertExpr->isTypeDependent() && !AssertExpr->isValueDependent() &&
      !Failed) {
    // In a static_assert-declaration, the constant-expression shall be a
    // constant expression that can be contextually converted to bool.
    ExprResult Converted = PerformContextuallyConvertToBool(AssertExpr);
    if (Converted.isInvalid())
      Failed = true;
    else
      Converted = ConstantExpr::Create(Context, Converted.get());

    llvm::APSInt Cond;
    if (!Failed && VerifyIntegerConstantExpression(Converted.get(), &Cond,
          diag::err_static_assert_expression_is_not_constant,
          /*AllowFold=*/false).isInvalid())
      Failed = true;

    if (!Failed && !Cond) {
      SmallString<256> MsgBuffer;
      llvm::raw_svector_ostream Msg(MsgBuffer);
      if (AssertMessage)
        AssertMessage->printPretty(Msg, nullptr, getPrintingPolicy());

      Expr *InnerCond = nullptr;
      std::string InnerCondDescription;
      std::tie(InnerCond, InnerCondDescription) =
        findFailedBooleanCondition(Converted.get());
      if (InnerCond && !isa<CXXBoolLiteralExpr>(InnerCond)
                    && !isa<IntegerLiteral>(InnerCond)) {
        Diag(StaticAssertLoc, diag::err_static_assert_requirement_failed)
          << InnerCondDescription << !AssertMessage
          << Msg.str() << InnerCond->getSourceRange();
      } else {
        Diag(StaticAssertLoc, diag::err_static_assert_failed)
          << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
      }
      Failed = true;
    }
  }

  ExprResult FullAssertExpr = ActOnFinishFullExpr(AssertExpr, StaticAssertLoc,
                                                  /*DiscardedValue*/false,
                                                  /*IsConstexpr*/true);
  if (FullAssertExpr.isInvalid())
    Failed = true;
  else
    AssertExpr = FullAssertExpr.get();

  Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc,
                                        AssertExpr, AssertMessage, RParenLoc,
                                        Failed);

  CurContext->addDecl(Decl);
  return Decl;
}

/// Perform semantic analysis of the given friend type declaration.
///
/// \returns A friend declaration that.
FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
                                      SourceLocation FriendLoc,
                                      TypeSourceInfo *TSInfo) {
  assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");

  QualType T = TSInfo->getType();
  SourceRange TypeRange = TSInfo->getTypeLoc().getLocalSourceRange();

  // C++03 [class.friend]p2:
  //   An elaborated-type-specifier shall be used in a friend declaration
  //   for a class.*
  //
  //   * The class-key of the elaborated-type-specifier is required.
  if (!CodeSynthesisContexts.empty()) {
    // Do not complain about the form of friend template types during any kind
    // of code synthesis. For template instantiation, we will have complained
    // when the template was defined.
  } else {
    if (!T->isElaboratedTypeSpecifier()) {
      // If we evaluated the type to a record type, suggest putting
      // a tag in front.
      if (const RecordType *RT = T->getAs<RecordType>()) {
        RecordDecl *RD = RT->getDecl();

        SmallString<16> InsertionText(" ");
        InsertionText += RD->getKindName();

        Diag(TypeRange.getBegin(),
             getLangOpts().CPlusPlus11 ?
               diag::warn_cxx98_compat_unelaborated_friend_type :
               diag::ext_unelaborated_friend_type)
          << (unsigned) RD->getTagKind()
          << T
          << FixItHint::CreateInsertion(getLocForEndOfToken(FriendLoc),
                                        InsertionText);
      } else {
        Diag(FriendLoc,
             getLangOpts().CPlusPlus11 ?
               diag::warn_cxx98_compat_nonclass_type_friend :
               diag::ext_nonclass_type_friend)
          << T
          << TypeRange;
      }
    } else if (T->getAs<EnumType>()) {
      Diag(FriendLoc,
           getLangOpts().CPlusPlus11 ?
             diag::warn_cxx98_compat_enum_friend :
             diag::ext_enum_friend)
        << T
        << TypeRange;
    }

    // C++11 [class.friend]p3:
    //   A friend declaration that does not declare a function shall have one
    //   of the following forms:
    //     friend elaborated-type-specifier ;
    //     friend simple-type-specifier ;
    //     friend typename-specifier ;
    if (getLangOpts().CPlusPlus11 && LocStart != FriendLoc)
      Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T;
  }

  //   If the type specifier in a friend declaration designates a (possibly
  //   cv-qualified) class type, that class is declared as a friend; otherwise,
  //   the friend declaration is ignored.
  return FriendDecl::Create(Context, CurContext,
                            TSInfo->getTypeLoc().getBeginLoc(), TSInfo,
                            FriendLoc);
}

/// Handle a friend tag declaration where the scope specifier was
/// templated.
Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
                                    unsigned TagSpec, SourceLocation TagLoc,
                                    CXXScopeSpec &SS, IdentifierInfo *Name,
                                    SourceLocation NameLoc,
                                    const ParsedAttributesView &Attr,
                                    MultiTemplateParamsArg TempParamLists) {
  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);

  bool IsMemberSpecialization = false;
  bool Invalid = false;

  if (TemplateParameterList *TemplateParams =
          MatchTemplateParametersToScopeSpecifier(
              TagLoc, NameLoc, SS, nullptr, TempParamLists, /*friend*/ true,
              IsMemberSpecialization, Invalid)) {
    if (TemplateParams->size() > 0) {
      // This is a declaration of a class template.
      if (Invalid)
        return nullptr;

      return CheckClassTemplate(S, TagSpec, TUK_Friend, TagLoc, SS, Name,
                                NameLoc, Attr, TemplateParams, AS_public,
                                /*ModulePrivateLoc=*/SourceLocation(),
                                FriendLoc, TempParamLists.size() - 1,
                                TempParamLists.data()).get();
    } else {
      // The "template<>" header is extraneous.
      Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams)
        << TypeWithKeyword::getTagTypeKindName(Kind) << Name;
      IsMemberSpecialization = true;
    }
  }

  if (Invalid) return nullptr;

  bool isAllExplicitSpecializations = true;
  for (unsigned I = TempParamLists.size(); I-- > 0; ) {
    if (TempParamLists[I]->size()) {
      isAllExplicitSpecializations = false;
      break;
    }
  }

  // FIXME: don't ignore attributes.

  // If it's explicit specializations all the way down, just forget
  // about the template header and build an appropriate non-templated
  // friend.  TODO: for source fidelity, remember the headers.
  if (isAllExplicitSpecializations) {
    if (SS.isEmpty()) {
      bool Owned = false;
      bool IsDependent = false;
      return ActOnTag(S, TagSpec, TUK_Friend, TagLoc, SS, Name, NameLoc,
                      Attr, AS_public,
                      /*ModulePrivateLoc=*/SourceLocation(),
                      MultiTemplateParamsArg(), Owned, IsDependent,
                      /*ScopedEnumKWLoc=*/SourceLocation(),
                      /*ScopedEnumUsesClassTag=*/false,
                      /*UnderlyingType=*/TypeResult(),
                      /*IsTypeSpecifier=*/false,
                      /*IsTemplateParamOrArg=*/false);
    }

    NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
    ElaboratedTypeKeyword Keyword
      = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
    QualType T = CheckTypenameType(Keyword, TagLoc, QualifierLoc,
                                   *Name, NameLoc);
    if (T.isNull())
      return nullptr;

    TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
    if (isa<DependentNameType>(T)) {
      DependentNameTypeLoc TL =
          TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
      TL.setElaboratedKeywordLoc(TagLoc);
      TL.setQualifierLoc(QualifierLoc);
      TL.setNameLoc(NameLoc);
    } else {
      ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs<ElaboratedTypeLoc>();
      TL.setElaboratedKeywordLoc(TagLoc);
      TL.setQualifierLoc(QualifierLoc);
      TL.getNamedTypeLoc().castAs<TypeSpecTypeLoc>().setNameLoc(NameLoc);
    }

    FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
                                            TSI, FriendLoc, TempParamLists);
    Friend->setAccess(AS_public);
    CurContext->addDecl(Friend);
    return Friend;
  }

  assert(SS.isNotEmpty() && "valid templated tag with no SS and no direct?");



  // Handle the case of a templated-scope friend class.  e.g.
  //   template <class T> class A<T>::B;
  // FIXME: we don't support these right now.
  Diag(NameLoc, diag::warn_template_qualified_friend_unsupported)
    << SS.getScopeRep() << SS.getRange() << cast<CXXRecordDecl>(CurContext);
  ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
  QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
  TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);
  DependentNameTypeLoc TL = TSI->getTypeLoc().castAs<DependentNameTypeLoc>();
  TL.setElaboratedKeywordLoc(TagLoc);
  TL.setQualifierLoc(SS.getWithLocInContext(Context));
  TL.setNameLoc(NameLoc);

  FriendDecl *Friend = FriendDecl::Create(Context, CurContext, NameLoc,
                                          TSI, FriendLoc, TempParamLists);
  Friend->setAccess(AS_public);
  Friend->setUnsupportedFriend(true);
  CurContext->addDecl(Friend);
  return Friend;
}

/// Handle a friend type declaration.  This works in tandem with
/// ActOnTag.
///
/// Notes on friend class templates:
///
/// We generally treat friend class declarations as if they were
/// declaring a class.  So, for example, the elaborated type specifier
/// in a friend declaration is required to obey the restrictions of a
/// class-head (i.e. no typedefs in the scope chain), template
/// parameters are required to match up with simple template-ids, &c.
/// However, unlike when declaring a template specialization, it's
/// okay to refer to a template specialization without an empty
/// template parameter declaration, e.g.
///   friend class A<T>::B<unsigned>;
/// We permit this as a special case; if there are any template
/// parameters present at all, require proper matching, i.e.
///   template <> template \<class T> friend class A<int>::B;
Decl *Sema::ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
                                MultiTemplateParamsArg TempParams) {
  SourceLocation Loc = DS.getBeginLoc();

  assert(DS.isFriendSpecified());
  assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);

  // C++ [class.friend]p3:
  // A friend declaration that does not declare a function shall have one of
  // the following forms:
  //     friend elaborated-type-specifier ;
  //     friend simple-type-specifier ;
  //     friend typename-specifier ;
  //
  // Any declaration with a type qualifier does not have that form. (It's
  // legal to specify a qualified type as a friend, you just can't write the
  // keywords.)
  if (DS.getTypeQualifiers()) {
    if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
      Diag(DS.getConstSpecLoc(), diag::err_friend_decl_spec) << "const";
    if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
      Diag(DS.getVolatileSpecLoc(), diag::err_friend_decl_spec) << "volatile";
    if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
      Diag(DS.getRestrictSpecLoc(), diag::err_friend_decl_spec) << "restrict";
    if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)
      Diag(DS.getAtomicSpecLoc(), diag::err_friend_decl_spec) << "_Atomic";
    if (DS.getTypeQualifiers() & DeclSpec::TQ_unaligned)
      Diag(DS.getUnalignedSpecLoc(), diag::err_friend_decl_spec) << "__unaligned";
  }

  // Try to convert the decl specifier to a type.  This works for
  // friend templates because ActOnTag never produces a ClassTemplateDecl
  // for a TUK_Friend.
  Declarator TheDeclarator(DS, DeclaratorContext::MemberContext);
  TypeSourceInfo *TSI = GetTypeForDeclarator(TheDeclarator, S);
  QualType T = TSI->getType();
  if (TheDeclarator.isInvalidType())
    return nullptr;

  if (DiagnoseUnexpandedParameterPack(Loc, TSI, UPPC_FriendDeclaration))
    return nullptr;

  // This is definitely an error in C++98.  It's probably meant to
  // be forbidden in C++0x, too, but the specification is just
  // poorly written.
  //
  // The problem is with declarations like the following:
  //   template <T> friend A<T>::foo;
  // where deciding whether a class C is a friend or not now hinges
  // on whether there exists an instantiation of A that causes
  // 'foo' to equal C.  There are restrictions on class-heads
  // (which we declare (by fiat) elaborated friend declarations to
  // be) that makes this tractable.
  //
  // FIXME: handle "template <> friend class A<T>;", which
  // is possibly well-formed?  Who even knows?
  if (TempParams.size() && !T->isElaboratedTypeSpecifier()) {
    Diag(Loc, diag::err_tagless_friend_type_template)
      << DS.getSourceRange();
    return nullptr;
  }

  // C++98 [class.friend]p1: A friend of a class is a function
  //   or class that is not a member of the class . . .
  // This is fixed in DR77, which just barely didn't make the C++03
  // deadline.  It's also a very silly restriction that seriously
  // affects inner classes and which nobody else seems to implement;
  // thus we never diagnose it, not even in -pedantic.
  //
  // But note that we could warn about it: it's always useless to
  // friend one of your own members (it's not, however, worthless to
  // friend a member of an arbitrary specialization of your template).

  Decl *D;
  if (!TempParams.empty())
    D = FriendTemplateDecl::Create(Context, CurContext, Loc,
                                   TempParams,
                                   TSI,
                                   DS.getFriendSpecLoc());
  else
    D = CheckFriendTypeDecl(Loc, DS.getFriendSpecLoc(), TSI);

  if (!D)
    return nullptr;

  D->setAccess(AS_public);
  CurContext->addDecl(D);

  return D;
}

NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
                                        MultiTemplateParamsArg TemplateParams) {
  const DeclSpec &DS = D.getDeclSpec();

  assert(DS.isFriendSpecified());
  assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);

  SourceLocation Loc = D.getIdentifierLoc();
  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);

  // C++ [class.friend]p1
  //   A friend of a class is a function or class....
  // Note that this sees through typedefs, which is intended.
  // It *doesn't* see through dependent types, which is correct
  // according to [temp.arg.type]p3:
  //   If a declaration acquires a function type through a
  //   type dependent on a template-parameter and this causes
  //   a declaration that does not use the syntactic form of a
  //   function declarator to have a function type, the program
  //   is ill-formed.
  if (!TInfo->getType()->isFunctionType()) {
    Diag(Loc, diag::err_unexpected_friend);

    // It might be worthwhile to try to recover by creating an
    // appropriate declaration.
    return nullptr;
  }

  // C++ [namespace.memdef]p3
  //  - If a friend declaration in a non-local class first declares a
  //    class or function, the friend class or function is a member
  //    of the innermost enclosing namespace.
  //  - The name of the friend is not found by simple name lookup
  //    until a matching declaration is provided in that namespace
  //    scope (either before or after the class declaration granting
  //    friendship).
  //  - If a friend function is called, its name may be found by the
  //    name lookup that considers functions from namespaces and
  //    classes associated with the types of the function arguments.
  //  - When looking for a prior declaration of a class or a function
  //    declared as a friend, scopes outside the innermost enclosing
  //    namespace scope are not considered.

  CXXScopeSpec &SS = D.getCXXScopeSpec();
  DeclarationNameInfo NameInfo = GetNameForDeclarator(D);
  assert(NameInfo.getName());

  // Check for unexpanded parameter packs.
  if (DiagnoseUnexpandedParameterPack(Loc, TInfo, UPPC_FriendDeclaration) ||
      DiagnoseUnexpandedParameterPack(NameInfo, UPPC_FriendDeclaration) ||
      DiagnoseUnexpandedParameterPack(SS, UPPC_FriendDeclaration))
    return nullptr;

  // The context we found the declaration in, or in which we should
  // create the declaration.
  DeclContext *DC;
  Scope *DCScope = S;
  LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
                        ForExternalRedeclaration);

  // There are five cases here.
  //   - There's no scope specifier and we're in a local class. Only look
  //     for functions declared in the immediately-enclosing block scope.
  // We recover from invalid scope qualifiers as if they just weren't there.
  FunctionDecl *FunctionContainingLocalClass = nullptr;
  if ((SS.isInvalid() || !SS.isSet()) &&
      (FunctionContainingLocalClass =
           cast<CXXRecordDecl>(CurContext)->isLocalClass())) {
    // C++11 [class.friend]p11:
    //   If a friend declaration appears in a local class and the name
    //   specified is an unqualified name, a prior declaration is
    //   looked up without considering scopes that are outside the
    //   innermost enclosing non-class scope. For a friend function
    //   declaration, if there is no prior declaration, the program is
    //   ill-formed.

    // Find the innermost enclosing non-class scope. This is the block
    // scope containing the local class definition (or for a nested class,
    // the outer local class).
    DCScope = S->getFnParent();

    // Look up the function name in the scope.
    Previous.clear(LookupLocalFriendName);
    LookupName(Previous, S, /*AllowBuiltinCreation*/false);

    if (!Previous.empty()) {
      // All possible previous declarations must have the same context:
      // either they were declared at block scope or they are members of
      // one of the enclosing local classes.
      DC = Previous.getRepresentativeDecl()->getDeclContext();
    } else {
      // This is ill-formed, but provide the context that we would have
      // declared the function in, if we were permitted to, for error recovery.
      DC = FunctionContainingLocalClass;
    }
    adjustContextForLocalExternDecl(DC);

    // C++ [class.friend]p6:
    //   A function can be defined in a friend declaration of a class if and
    //   only if the class is a non-local class (9.8), the function name is
    //   unqualified, and the function has namespace scope.
    if (D.isFunctionDefinition()) {
      Diag(NameInfo.getBeginLoc(), diag::err_friend_def_in_local_class);
    }

  //   - There's no scope specifier, in which case we just go to the
  //     appropriate scope and look for a function or function template
  //     there as appropriate.
  } else if (SS.isInvalid() || !SS.isSet()) {
    // C++11 [namespace.memdef]p3:
    //   If the name in a friend declaration is neither qualified nor
    //   a template-id and the declaration is a function or an
    //   elaborated-type-specifier, the lookup to determine whether
    //   the entity has been previously declared shall not consider
    //   any scopes outside the innermost enclosing namespace.
    bool isTemplateId =
        D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId;

    // Find the appropriate context according to the above.
    DC = CurContext;

    // Skip class contexts.  If someone can cite chapter and verse
    // for this behavior, that would be nice --- it's what GCC and
    // EDG do, and it seems like a reasonable intent, but the spec
    // really only says that checks for unqualified existing
    // declarations should stop at the nearest enclosing namespace,
    // not that they should only consider the nearest enclosing
    // namespace.
    while (DC->isRecord())
      DC = DC->getParent();

    DeclContext *LookupDC = DC;
    while (LookupDC->isTransparentContext())
      LookupDC = LookupDC->getParent();

    while (true) {
      LookupQualifiedName(Previous, LookupDC);

      if (!Previous.empty()) {
        DC = LookupDC;
        break;
      }

      if (isTemplateId) {
        if (isa<TranslationUnitDecl>(LookupDC)) break;
      } else {
        if (LookupDC->isFileContext()) break;
      }
      LookupDC = LookupDC->getParent();
    }

    DCScope = getScopeForDeclContext(S, DC);

  //   - There's a non-dependent scope specifier, in which case we
  //     compute it and do a previous lookup there for a function
  //     or function template.
  } else if (!SS.getScopeRep()->isDependent()) {
    DC = computeDeclContext(SS);
    if (!DC) return nullptr;

    if (RequireCompleteDeclContext(SS, DC)) return nullptr;

    LookupQualifiedName(Previous, DC);

    // C++ [class.friend]p1: A friend of a class is a function or
    //   class that is not a member of the class . . .
    if (DC->Equals(CurContext))
      Diag(DS.getFriendSpecLoc(),
           getLangOpts().CPlusPlus11 ?
             diag::warn_cxx98_compat_friend_is_member :
             diag::err_friend_is_member);

    if (D.isFunctionDefinition()) {
      // C++ [class.friend]p6:
      //   A function can be defined in a friend declaration of a class if and
      //   only if the class is a non-local class (9.8), the function name is
      //   unqualified, and the function has namespace scope.
      //
      // FIXME: We should only do this if the scope specifier names the
      // innermost enclosing namespace; otherwise the fixit changes the
      // meaning of the code.
      SemaDiagnosticBuilder DB
        = Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def);

      DB << SS.getScopeRep();
      if (DC->isFileContext())
        DB << FixItHint::CreateRemoval(SS.getRange());
      SS.clear();
    }

  //   - There's a scope specifier that does not match any template
  //     parameter lists, in which case we use some arbitrary context,
  //     create a method or method template, and wait for instantiation.
  //   - There's a scope specifier that does match some template
  //     parameter lists, which we don't handle right now.
  } else {
    if (D.isFunctionDefinition()) {
      // C++ [class.friend]p6:
      //   A function can be defined in a friend declaration of a class if and
      //   only if the class is a non-local class (9.8), the function name is
      //   unqualified, and the function has namespace scope.
      Diag(SS.getRange().getBegin(), diag::err_qualified_friend_def)
        << SS.getScopeRep();
    }

    DC = CurContext;
    assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?");
  }

  if (!DC->isRecord()) {
    int DiagArg = -1;
    switch (D.getName().getKind()) {
    case UnqualifiedIdKind::IK_ConstructorTemplateId:
    case UnqualifiedIdKind::IK_ConstructorName:
      DiagArg = 0;
      break;
    case UnqualifiedIdKind::IK_DestructorName:
      DiagArg = 1;
      break;
    case UnqualifiedIdKind::IK_ConversionFunctionId:
      DiagArg = 2;
      break;
    case UnqualifiedIdKind::IK_DeductionGuideName:
      DiagArg = 3;
      break;
    case UnqualifiedIdKind::IK_Identifier:
    case UnqualifiedIdKind::IK_ImplicitSelfParam:
    case UnqualifiedIdKind::IK_LiteralOperatorId:
    case UnqualifiedIdKind::IK_OperatorFunctionId:
    case UnqualifiedIdKind::IK_TemplateId:
      break;
    }
    // This implies that it has to be an operator or function.
    if (DiagArg >= 0) {
      Diag(Loc, diag::err_introducing_special_friend) << DiagArg;
      return nullptr;
    }
  }

  // FIXME: This is an egregious hack to cope with cases where the scope stack
  // does not contain the declaration context, i.e., in an out-of-line
  // definition of a class.
  Scope FakeDCScope(S, Scope::DeclScope, Diags);
  if (!DCScope) {
    FakeDCScope.setEntity(DC);
    DCScope = &FakeDCScope;
  }

  bool AddToScope = true;
  NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, TInfo, Previous,
                                          TemplateParams, AddToScope);
  if (!ND) return nullptr;

  assert(ND->getLexicalDeclContext() == CurContext);

  // If we performed typo correction, we might have added a scope specifier
  // and changed the decl context.
  DC = ND->getDeclContext();

  // Add the function declaration to the appropriate lookup tables,
  // adjusting the redeclarations list as necessary.  We don't
  // want to do this yet if the friending class is dependent.
  //
  // Also update the scope-based lookup if the target context's
  // lookup context is in lexical scope.
  if (!CurContext->isDependentContext()) {
    DC = DC->getRedeclContext();
    DC->makeDeclVisibleInContext(ND);
    if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
      PushOnScopeChains(ND, EnclosingScope, /*AddToContext=*/ false);
  }

  FriendDecl *FrD = FriendDecl::Create(Context, CurContext,
                                       D.getIdentifierLoc(), ND,
                                       DS.getFriendSpecLoc());
  FrD->setAccess(AS_public);
  CurContext->addDecl(FrD);

  if (ND->isInvalidDecl()) {
    FrD->setInvalidDecl();
  } else {
    if (DC->isRecord()) CheckFriendAccess(ND);

    FunctionDecl *FD;
    if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
      FD = FTD->getTemplatedDecl();
    else
      FD = cast<FunctionDecl>(ND);

    // C++11 [dcl.fct.default]p4: If a friend declaration specifies a
    // default argument expression, that declaration shall be a definition
    // and shall be the only declaration of the function or function
    // template in the translation unit.
    if (functionDeclHasDefaultArgument(FD)) {
      // We can't look at FD->getPreviousDecl() because it may not have been set
      // if we're in a dependent context. If the function is known to be a
      // redeclaration, we will have narrowed Previous down to the right decl.
      if (D.isRedeclaration()) {
        Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_redeclared);
        Diag(Previous.getRepresentativeDecl()->getLocation(),
             diag::note_previous_declaration);
      } else if (!D.isFunctionDefinition())
        Diag(FD->getLocation(), diag::err_friend_decl_with_def_arg_must_be_def);
    }

    // Mark templated-scope function declarations as unsupported.
    if (FD->getNumTemplateParameterLists() && SS.isValid()) {
      Diag(FD->getLocation(), diag::warn_template_qualified_friend_unsupported)
        << SS.getScopeRep() << SS.getRange()
        << cast<CXXRecordDecl>(CurContext);
      FrD->setUnsupportedFriend(true);
    }
  }

  return ND;
}

void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
  AdjustDeclIfTemplate(Dcl);

  FunctionDecl *Fn = dyn_cast_or_null<FunctionDecl>(Dcl);
  if (!Fn) {
    Diag(DelLoc, diag::err_deleted_non_function);
    return;
  }

  // Deleted function does not have a body.
  Fn->setWillHaveBody(false);

  if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
    // Don't consider the implicit declaration we generate for explicit
    // specializations. FIXME: Do not generate these implicit declarations.
    if ((Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization ||
         Prev->getPreviousDecl()) &&
        !Prev->isDefined()) {
      Diag(DelLoc, diag::err_deleted_decl_not_first);
      Diag(Prev->getLocation().isInvalid() ? DelLoc : Prev->getLocation(),
           Prev->isImplicit() ? diag::note_previous_implicit_declaration
                              : diag::note_previous_declaration);
    }
    // If the declaration wasn't the first, we delete the function anyway for
    // recovery.
    Fn = Fn->getCanonicalDecl();
  }

  // dllimport/dllexport cannot be deleted.
  if (const InheritableAttr *DLLAttr = getDLLAttr(Fn)) {
    Diag(Fn->getLocation(), diag::err_attribute_dll_deleted) << DLLAttr;
    Fn->setInvalidDecl();
  }

  if (Fn->isDeleted())
    return;

  // See if we're deleting a function which is already known to override a
  // non-deleted virtual function.
  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn)) {
    bool IssuedDiagnostic = false;
    for (const CXXMethodDecl *O : MD->overridden_methods()) {
      if (!(*MD->begin_overridden_methods())->isDeleted()) {
        if (!IssuedDiagnostic) {
          Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
          IssuedDiagnostic = true;
        }
        Diag(O->getLocation(), diag::note_overridden_virtual_function);
      }
    }
    // If this function was implicitly deleted because it was defaulted,
    // explain why it was deleted.
    if (IssuedDiagnostic && MD->isDefaulted())
      ShouldDeleteSpecialMember(MD, getSpecialMember(MD), nullptr,
                                /*Diagnose*/true);
  }

  // C++11 [basic.start.main]p3:
  //   A program that defines main as deleted [...] is ill-formed.
  if (Fn->isMain())
    Diag(DelLoc, diag::err_deleted_main);

  // C++11 [dcl.fct.def.delete]p4:
  //  A deleted function is implicitly inline.
  Fn->setImplicitlyInline();
  Fn->setDeletedAsWritten();
}

void Sema::SetDeclDefaulted(Decl *Dcl, SourceLocation DefaultLoc) {
  CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Dcl);

  if (MD) {
    if (MD->getParent()->isDependentType()) {
      MD->setDefaulted();
      MD->setExplicitlyDefaulted();
      return;
    }

    CXXSpecialMember Member = getSpecialMember(MD);
    if (Member == CXXInvalid) {
      if (!MD->isInvalidDecl())
        Diag(DefaultLoc, diag::err_default_special_members);
      return;
    }

    MD->setDefaulted();
    MD->setExplicitlyDefaulted();

    // Unset that we will have a body for this function. We might not,
    // if it turns out to be trivial, and we don't need this marking now
    // that we've marked it as defaulted.
    MD->setWillHaveBody(false);

    // If this definition appears within the record, do the checking when
    // the record is complete.
    const FunctionDecl *Primary = MD;
    if (const FunctionDecl *Pattern = MD->getTemplateInstantiationPattern())
      // Ask the template instantiation pattern that actually had the
      // '= default' on it.
      Primary = Pattern;

    // If the method was defaulted on its first declaration, we will have
    // already performed the checking in CheckCompletedCXXClass. Such a
    // declaration doesn't trigger an implicit definition.
    if (Primary->getCanonicalDecl()->isDefaulted())
      return;

    CheckExplicitlyDefaultedSpecialMember(MD);

    if (!MD->isInvalidDecl())
      DefineImplicitSpecialMember(*this, MD, DefaultLoc);
  } else {
    Diag(DefaultLoc, diag::err_default_special_members);
  }
}

static void SearchForReturnInStmt(Sema &Self, Stmt *S) {
  for (Stmt *SubStmt : S->children()) {
    if (!SubStmt)
      continue;
    if (isa<ReturnStmt>(SubStmt))
      Self.Diag(SubStmt->getBeginLoc(),
                diag::err_return_in_constructor_handler);
    if (!isa<Expr>(SubStmt))
      SearchForReturnInStmt(Self, SubStmt);
  }
}

void Sema::DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock) {
  for (unsigned I = 0, E = TryBlock->getNumHandlers(); I != E; ++I) {
    CXXCatchStmt *Handler = TryBlock->getHandler(I);
    SearchForReturnInStmt(*this, Handler);
  }
}

bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
                                             const CXXMethodDecl *Old) {
  const auto *NewFT = New->getType()->getAs<FunctionProtoType>();
  const auto *OldFT = Old->getType()->getAs<FunctionProtoType>();

  if (OldFT->hasExtParameterInfos()) {
    for (unsigned I = 0, E = OldFT->getNumParams(); I != E; ++I)
      // A parameter of the overriding method should be annotated with noescape
      // if the corresponding parameter of the overridden method is annotated.
      if (OldFT->getExtParameterInfo(I).isNoEscape() &&
          !NewFT->getExtParameterInfo(I).isNoEscape()) {
        Diag(New->getParamDecl(I)->getLocation(),
             diag::warn_overriding_method_missing_noescape);
        Diag(Old->getParamDecl(I)->getLocation(),
             diag::note_overridden_marked_noescape);
      }
  }

  // Virtual overrides must have the same code_seg.
  const auto *OldCSA = Old->getAttr<CodeSegAttr>();
  const auto *NewCSA = New->getAttr<CodeSegAttr>();
  if ((NewCSA || OldCSA) &&
      (!OldCSA || !NewCSA || NewCSA->getName() != OldCSA->getName())) {
    Diag(New->getLocation(), diag::err_mismatched_code_seg_override);
    Diag(Old->getLocation(), diag::note_previous_declaration);
    return true;
  }

  CallingConv NewCC = NewFT->getCallConv(), OldCC = OldFT->getCallConv();

  // If the calling conventions match, everything is fine
  if (NewCC == OldCC)
    return false;

  // If the calling conventions mismatch because the new function is static,
  // suppress the calling convention mismatch error; the error about static
  // function override (err_static_overrides_virtual from
  // Sema::CheckFunctionDeclaration) is more clear.
  if (New->getStorageClass() == SC_Static)
    return false;

  Diag(New->getLocation(),
       diag::err_conflicting_overriding_cc_attributes)
    << New->getDeclName() << New->getType() << Old->getType();
  Diag(Old->getLocation(), diag::note_overridden_virtual_function);
  return true;
}

bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
                                             const CXXMethodDecl *Old) {
  QualType NewTy = New->getType()->getAs<FunctionType>()->getReturnType();
  QualType OldTy = Old->getType()->getAs<FunctionType>()->getReturnType();

  if (Context.hasSameType(NewTy, OldTy) ||
      NewTy->isDependentType() || OldTy->isDependentType())
    return false;

  // Check if the return types are covariant
  QualType NewClassTy, OldClassTy;

  /// Both types must be pointers or references to classes.
  if (const PointerType *NewPT = NewTy->getAs<PointerType>()) {
    if (const PointerType *OldPT = OldTy->getAs<PointerType>()) {
      NewClassTy = NewPT->getPointeeType();
      OldClassTy = OldPT->getPointeeType();
    }
  } else if (const ReferenceType *NewRT = NewTy->getAs<ReferenceType>()) {
    if (const ReferenceType *OldRT = OldTy->getAs<ReferenceType>()) {
      if (NewRT->getTypeClass() == OldRT->getTypeClass()) {
        NewClassTy = NewRT->getPointeeType();
        OldClassTy = OldRT->getPointeeType();
      }
    }
  }

  // The return types aren't either both pointers or references to a class type.
  if (NewClassTy.isNull()) {
    Diag(New->getLocation(),
         diag::err_different_return_type_for_overriding_virtual_function)
        << New->getDeclName() << NewTy << OldTy
        << New->getReturnTypeSourceRange();
    Diag(Old->getLocation(), diag::note_overridden_virtual_function)
        << Old->getReturnTypeSourceRange();

    return true;
  }

  if (!Context.hasSameUnqualifiedType(NewClassTy, OldClassTy)) {
    // C++14 [class.virtual]p8:
    //   If the class type in the covariant return type of D::f differs from
    //   that of B::f, the class type in the return type of D::f shall be
    //   complete at the point of declaration of D::f or shall be the class
    //   type D.
    if (const RecordType *RT = NewClassTy->getAs<RecordType>()) {
      if (!RT->isBeingDefined() &&
          RequireCompleteType(New->getLocation(), NewClassTy,
                              diag::err_covariant_return_incomplete,
                              New->getDeclName()))
        return true;
    }

    // Check if the new class derives from the old class.
    if (!IsDerivedFrom(New->getLocation(), NewClassTy, OldClassTy)) {
      Diag(New->getLocation(), diag::err_covariant_return_not_derived)
          << New->getDeclName() << NewTy << OldTy
          << New->getReturnTypeSourceRange();
      Diag(Old->getLocation(), diag::note_overridden_virtual_function)
          << Old->getReturnTypeSourceRange();
      return true;
    }

    // Check if we the conversion from derived to base is valid.
    if (CheckDerivedToBaseConversion(
            NewClassTy, OldClassTy,
            diag::err_covariant_return_inaccessible_base,
            diag::err_covariant_return_ambiguous_derived_to_base_conv,
            New->getLocation(), New->getReturnTypeSourceRange(),
            New->getDeclName(), nullptr)) {
      // FIXME: this note won't trigger for delayed access control
      // diagnostics, and it's impossible to get an undelayed error
      // here from access control during the original parse because
      // the ParsingDeclSpec/ParsingDeclarator are still in scope.
      Diag(Old->getLocation(), diag::note_overridden_virtual_function)
          << Old->getReturnTypeSourceRange();
      return true;
    }
  }

  // The qualifiers of the return types must be the same.
  if (NewTy.getLocalCVRQualifiers() != OldTy.getLocalCVRQualifiers()) {
    Diag(New->getLocation(),
         diag::err_covariant_return_type_different_qualifications)
        << New->getDeclName() << NewTy << OldTy
        << New->getReturnTypeSourceRange();
    Diag(Old->getLocation(), diag::note_overridden_virtual_function)
        << Old->getReturnTypeSourceRange();
    return true;
  }


  // The new class type must have the same or less qualifiers as the old type.
  if (NewClassTy.isMoreQualifiedThan(OldClassTy)) {
    Diag(New->getLocation(),
         diag::err_covariant_return_type_class_type_more_qualified)
        << New->getDeclName() << NewTy << OldTy
        << New->getReturnTypeSourceRange();
    Diag(Old->getLocation(), diag::note_overridden_virtual_function)
        << Old->getReturnTypeSourceRange();
    return true;
  }

  return false;
}

/// Mark the given method pure.
///
/// \param Method the method to be marked pure.
///
/// \param InitRange the source range that covers the "0" initializer.
bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) {
  SourceLocation EndLoc = InitRange.getEnd();
  if (EndLoc.isValid())
    Method->setRangeEnd(EndLoc);

  if (Method->isVirtual() || Method->getParent()->isDependentContext()) {
    Method->setPure();
    return false;
  }

  if (!Method->isInvalidDecl())
    Diag(Method->getLocation(), diag::err_non_virtual_pure)
      << Method->getDeclName() << InitRange;
  return true;
}

void Sema::ActOnPureSpecifier(Decl *D, SourceLocation ZeroLoc) {
  if (D->getFriendObjectKind())
    Diag(D->getLocation(), diag::err_pure_friend);
  else if (auto *M = dyn_cast<CXXMethodDecl>(D))
    CheckPureMethod(M, ZeroLoc);
  else
    Diag(D->getLocation(), diag::err_illegal_initializer);
}

/// Determine whether the given declaration is a global variable or
/// static data member.
static bool isNonlocalVariable(const Decl *D) {
  if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
    return Var->hasGlobalStorage();

  return false;
}

/// Invoked when we are about to parse an initializer for the declaration
/// 'Dcl'.
///
/// After this method is called, according to [C++ 3.4.1p13], if 'Dcl' is a
/// static data member of class X, names should be looked up in the scope of
/// class X. If the declaration had a scope specifier, a scope will have
/// been created and passed in for this purpose. Otherwise, S will be null.
void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) {
  // If there is no declaration, there was an error parsing it.
  if (!D || D->isInvalidDecl())
    return;

  // We will always have a nested name specifier here, but this declaration
  // might not be out of line if the specifier names the current namespace:
  //   extern int n;
  //   int ::n = 0;
  if (S && D->isOutOfLine())
    EnterDeclaratorContext(S, D->getDeclContext());

  // If we are parsing the initializer for a static data member, push a
  // new expression evaluation context that is associated with this static
  // data member.
  if (isNonlocalVariable(D))
    PushExpressionEvaluationContext(
        ExpressionEvaluationContext::PotentiallyEvaluated, D);
}

/// Invoked after we are finished parsing an initializer for the declaration D.
void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) {
  // If there is no declaration, there was an error parsing it.
  if (!D || D->isInvalidDecl())
    return;

  if (isNonlocalVariable(D))
    PopExpressionEvaluationContext();

  if (S && D->isOutOfLine())
    ExitDeclaratorContext(S);
}

/// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a
/// C++ if/switch/while/for statement.
/// e.g: "if (int x = f()) {...}"
DeclResult Sema::ActOnCXXConditionDeclaration(Scope *S, Declarator &D) {
  // C++ 6.4p2:
  // The declarator shall not specify a function or an array.
  // The type-specifier-seq shall not contain typedef and shall not declare a
  // new class or enumeration.
  assert(D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
         "Parser allowed 'typedef' as storage class of condition decl.");

  Decl *Dcl = ActOnDeclarator(S, D);
  if (!Dcl)
    return true;

  if (isa<FunctionDecl>(Dcl)) { // The declarator shall not specify a function.
    Diag(Dcl->getLocation(), diag::err_invalid_use_of_function_type)
      << D.getSourceRange();
    return true;
  }

  return Dcl;
}

void Sema::LoadExternalVTableUses() {
  if (!ExternalSource)
    return;

  SmallVector<ExternalVTableUse, 4> VTables;
  ExternalSource->ReadUsedVTables(VTables);
  SmallVector<VTableUse, 4> NewUses;
  for (unsigned I = 0, N = VTables.size(); I != N; ++I) {
    llvm::DenseMap<CXXRecordDecl *, bool>::iterator Pos
      = VTablesUsed.find(VTables[I].Record);
    // Even if a definition wasn't required before, it may be required now.
    if (Pos != VTablesUsed.end()) {
      if (!Pos->second && VTables[I].DefinitionRequired)
        Pos->second = true;
      continue;
    }

    VTablesUsed[VTables[I].Record] = VTables[I].DefinitionRequired;
    NewUses.push_back(VTableUse(VTables[I].Record, VTables[I].Location));
  }

  VTableUses.insert(VTableUses.begin(), NewUses.begin(), NewUses.end());
}

void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
                          bool DefinitionRequired) {
  // Ignore any vtable uses in unevaluated operands or for classes that do
  // not have a vtable.
  if (!Class->isDynamicClass() || Class->isDependentContext() ||
      CurContext->isDependentContext() || isUnevaluatedContext())
    return;
  // Do not mark as used if compiling for the device outside of the target
  // region.
  if (LangOpts.OpenMP && LangOpts.OpenMPIsDevice &&
      !isInOpenMPDeclareTargetContext() &&
      !isInOpenMPTargetExecutionDirective()) {
    if (!DefinitionRequired)
      MarkVirtualMembersReferenced(Loc, Class);
    return;
  }

  // Try to insert this class into the map.
  LoadExternalVTableUses();
  Class = Class->getCanonicalDecl();
  std::pair<llvm::DenseMap<CXXRecordDecl *, bool>::iterator, bool>
    Pos = VTablesUsed.insert(std::make_pair(Class, DefinitionRequired));
  if (!Pos.second) {
    // If we already had an entry, check to see if we are promoting this vtable
    // to require a definition. If so, we need to reappend to the VTableUses
    // list, since we may have already processed the first entry.
    if (DefinitionRequired && !Pos.first->second) {
      Pos.first->second = true;
    } else {
      // Otherwise, we can early exit.
      return;
    }
  } else {
    // The Microsoft ABI requires that we perform the destructor body
    // checks (i.e. operator delete() lookup) when the vtable is marked used, as
    // the deleting destructor is emitted with the vtable, not with the
    // destructor definition as in the Itanium ABI.
    if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
      CXXDestructorDecl *DD = Class->getDestructor();
      if (DD && DD->isVirtual() && !DD->isDeleted()) {
        if (Class->hasUserDeclaredDestructor() && !DD->isDefined()) {
          // If this is an out-of-line declaration, marking it referenced will
          // not do anything. Manually call CheckDestructor to look up operator
          // delete().
          ContextRAII SavedContext(*this, DD);
          CheckDestructor(DD);
        } else {
          MarkFunctionReferenced(Loc, Class->getDestructor());
        }
      }
    }
  }

  // Local classes need to have their virtual members marked
  // immediately. For all other classes, we mark their virtual members
  // at the end of the translation unit.
  if (Class->isLocalClass())
    MarkVirtualMembersReferenced(Loc, Class);
  else
    VTableUses.push_back(std::make_pair(Class, Loc));
}

bool Sema::DefineUsedVTables() {
  LoadExternalVTableUses();
  if (VTableUses.empty())
    return false;

  // Note: The VTableUses vector could grow as a result of marking
  // the members of a class as "used", so we check the size each
  // time through the loop and prefer indices (which are stable) to
  // iterators (which are not).
  bool DefinedAnything = false;
  for (unsigned I = 0; I != VTableUses.size(); ++I) {
    CXXRecordDecl *Class = VTableUses[I].first->getDefinition();
    if (!Class)
      continue;
    TemplateSpecializationKind ClassTSK =
        Class->getTemplateSpecializationKind();

    SourceLocation Loc = VTableUses[I].second;

    bool DefineVTable = true;

    // If this class has a key function, but that key function is
    // defined in another translation unit, we don't need to emit the
    // vtable even though we're using it.
    const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class);
    if (KeyFunction && !KeyFunction->hasBody()) {
      // The key function is in another translation unit.
      DefineVTable = false;
      TemplateSpecializationKind TSK =
          KeyFunction->getTemplateSpecializationKind();
      assert(TSK != TSK_ExplicitInstantiationDefinition &&
             TSK != TSK_ImplicitInstantiation &&
             "Instantiations don't have key functions");
      (void)TSK;
    } else if (!KeyFunction) {
      // If we have a class with no key function that is the subject
      // of an explicit instantiation declaration, suppress the
      // vtable; it will live with the explicit instantiation
      // definition.
      bool IsExplicitInstantiationDeclaration =
          ClassTSK == TSK_ExplicitInstantiationDeclaration;
      for (auto R : Class->redecls()) {
        TemplateSpecializationKind TSK
          = cast<CXXRecordDecl>(R)->getTemplateSpecializationKind();
        if (TSK == TSK_ExplicitInstantiationDeclaration)
          IsExplicitInstantiationDeclaration = true;
        else if (TSK == TSK_ExplicitInstantiationDefinition) {
          IsExplicitInstantiationDeclaration = false;
          break;
        }
      }

      if (IsExplicitInstantiationDeclaration)
        DefineVTable = false;
    }

    // The exception specifications for all virtual members may be needed even
    // if we are not providing an authoritative form of the vtable in this TU.
    // We may choose to emit it available_externally anyway.
    if (!DefineVTable) {
      MarkVirtualMemberExceptionSpecsNeeded(Loc, Class);
      continue;
    }

    // Mark all of the virtual members of this class as referenced, so
    // that we can build a vtable. Then, tell the AST consumer that a
    // vtable for this class is required.
    DefinedAnything = true;
    MarkVirtualMembersReferenced(Loc, Class);
    CXXRecordDecl *Canonical = Class->getCanonicalDecl();
    if (VTablesUsed[Canonical])
      Consumer.HandleVTable(Class);

    // Warn if we're emitting a weak vtable. The vtable will be weak if there is
    // no key function or the key function is inlined. Don't warn in C++ ABIs
    // that lack key functions, since the user won't be able to make one.
    if (Context.getTargetInfo().getCXXABI().hasKeyFunctions() &&
        Class->isExternallyVisible() && ClassTSK != TSK_ImplicitInstantiation) {
      const FunctionDecl *KeyFunctionDef = nullptr;
      if (!KeyFunction || (KeyFunction->hasBody(KeyFunctionDef) &&
                           KeyFunctionDef->isInlined())) {
        Diag(Class->getLocation(),
             ClassTSK == TSK_ExplicitInstantiationDefinition
                 ? diag::warn_weak_template_vtable
                 : diag::warn_weak_vtable)
            << Class;
      }
    }
  }
  VTableUses.clear();

  return DefinedAnything;
}

void Sema::MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc,
                                                 const CXXRecordDecl *RD) {
  for (const auto *I : RD->methods())
    if (I->isVirtual() && !I->isPure())
      ResolveExceptionSpec(Loc, I->getType()->castAs<FunctionProtoType>());
}

void Sema::MarkVirtualMembersReferenced(SourceLocation Loc,
                                        const CXXRecordDecl *RD,
                                        bool ConstexprOnly) {
  // Mark all functions which will appear in RD's vtable as used.
  CXXFinalOverriderMap FinalOverriders;
  RD->getFinalOverriders(FinalOverriders);
  for (CXXFinalOverriderMap::const_iterator I = FinalOverriders.begin(),
                                            E = FinalOverriders.end();
       I != E; ++I) {
    for (OverridingMethods::const_iterator OI = I->second.begin(),
                                           OE = I->second.end();
         OI != OE; ++OI) {
      assert(OI->second.size() > 0 && "no final overrider");
      CXXMethodDecl *Overrider = OI->second.front().Method;

      // C++ [basic.def.odr]p2:
      //   [...] A virtual member function is used if it is not pure. [...]
      if (!Overrider->isPure() && (!ConstexprOnly || Overrider->isConstexpr()))
        MarkFunctionReferenced(Loc, Overrider);
    }
  }

  // Only classes that have virtual bases need a VTT.
  if (RD->getNumVBases() == 0)
    return;

  for (const auto &I : RD->bases()) {
    const CXXRecordDecl *Base =
        cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
    if (Base->getNumVBases() == 0)
      continue;
    MarkVirtualMembersReferenced(Loc, Base);
  }
}

/// SetIvarInitializers - This routine builds initialization ASTs for the
/// Objective-C implementation whose ivars need be initialized.
void Sema::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
  if (!getLangOpts().CPlusPlus)
    return;
  if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
    SmallVector<ObjCIvarDecl*, 8> ivars;
    CollectIvarsToConstructOrDestruct(OID, ivars);
    if (ivars.empty())
      return;
    SmallVector<CXXCtorInitializer*, 32> AllToInit;
    for (unsigned i = 0; i < ivars.size(); i++) {
      FieldDecl *Field = ivars[i];
      if (Field->isInvalidDecl())
        continue;

      CXXCtorInitializer *Member;
      InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
      InitializationKind InitKind =
        InitializationKind::CreateDefault(ObjCImplementation->getLocation());

      InitializationSequence InitSeq(*this, InitEntity, InitKind, None);
      ExprResult MemberInit =
        InitSeq.Perform(*this, InitEntity, InitKind, None);
      MemberInit = MaybeCreateExprWithCleanups(MemberInit);
      // Note, MemberInit could actually come back empty if no initialization
      // is required (e.g., because it would call a trivial default constructor)
      if (!MemberInit.get() || MemberInit.isInvalid())
        continue;

      Member =
        new (Context) CXXCtorInitializer(Context, Field, SourceLocation(),
                                         SourceLocation(),
                                         MemberInit.getAs<Expr>(),
                                         SourceLocation());
      AllToInit.push_back(Member);

      // Be sure that the destructor is accessible and is marked as referenced.
      if (const RecordType *RecordTy =
              Context.getBaseElementType(Field->getType())
                  ->getAs<RecordType>()) {
        CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
        if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) {
          MarkFunctionReferenced(Field->getLocation(), Destructor);
          CheckDestructorAccess(Field->getLocation(), Destructor,
                            PDiag(diag::err_access_dtor_ivar)
                              << Context.getBaseElementType(Field->getType()));
        }
      }
    }
    ObjCImplementation->setIvarInitializers(Context,
                                            AllToInit.data(), AllToInit.size());
  }
}

static
void DelegatingCycleHelper(CXXConstructorDecl* Ctor,
                           llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Valid,
                           llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Invalid,
                           llvm::SmallPtrSet<CXXConstructorDecl*, 4> &Current,
                           Sema &S) {
  if (Ctor->isInvalidDecl())
    return;

  CXXConstructorDecl *Target = Ctor->getTargetConstructor();

  // Target may not be determinable yet, for instance if this is a dependent
  // call in an uninstantiated template.
  if (Target) {
    const FunctionDecl *FNTarget = nullptr;
    (void)Target->hasBody(FNTarget);
    Target = const_cast<CXXConstructorDecl*>(
      cast_or_null<CXXConstructorDecl>(FNTarget));
  }

  CXXConstructorDecl *Canonical = Ctor->getCanonicalDecl(),
                     // Avoid dereferencing a null pointer here.
                     *TCanonical = Target? Target->getCanonicalDecl() : nullptr;

  if (!Current.insert(Canonical).second)
    return;

  // We know that beyond here, we aren't chaining into a cycle.
  if (!Target || !Target->isDelegatingConstructor() ||
      Target->isInvalidDecl() || Valid.count(TCanonical)) {
    Valid.insert(Current.begin(), Current.end());
    Current.clear();
  // We've hit a cycle.
  } else if (TCanonical == Canonical || Invalid.count(TCanonical) ||
             Current.count(TCanonical)) {
    // If we haven't diagnosed this cycle yet, do so now.
    if (!Invalid.count(TCanonical)) {
      S.Diag((*Ctor->init_begin())->getSourceLocation(),
             diag::warn_delegating_ctor_cycle)
        << Ctor;

      // Don't add a note for a function delegating directly to itself.
      if (TCanonical != Canonical)
        S.Diag(Target->getLocation(), diag::note_it_delegates_to);

      CXXConstructorDecl *C = Target;
      while (C->getCanonicalDecl() != Canonical) {
        const FunctionDecl *FNTarget = nullptr;
        (void)C->getTargetConstructor()->hasBody(FNTarget);
        assert(FNTarget && "Ctor cycle through bodiless function");

        C = const_cast<CXXConstructorDecl*>(
          cast<CXXConstructorDecl>(FNTarget));
        S.Diag(C->getLocation(), diag::note_which_delegates_to);
      }
    }

    Invalid.insert(Current.begin(), Current.end());
    Current.clear();
  } else {
    DelegatingCycleHelper(Target, Valid, Invalid, Current, S);
  }
}


void Sema::CheckDelegatingCtorCycles() {
  llvm::SmallPtrSet<CXXConstructorDecl*, 4> Valid, Invalid, Current;

  for (DelegatingCtorDeclsType::iterator
         I = DelegatingCtorDecls.begin(ExternalSource),
         E = DelegatingCtorDecls.end();
       I != E; ++I)
    DelegatingCycleHelper(*I, Valid, Invalid, Current, *this);

  for (auto CI = Invalid.begin(), CE = Invalid.end(); CI != CE; ++CI)
    (*CI)->setInvalidDecl();
}

namespace {
  /// AST visitor that finds references to the 'this' expression.
  class FindCXXThisExpr : public RecursiveASTVisitor<FindCXXThisExpr> {
    Sema &S;

  public:
    explicit FindCXXThisExpr(Sema &S) : S(S) { }

    bool VisitCXXThisExpr(CXXThisExpr *E) {
      S.Diag(E->getLocation(), diag::err_this_static_member_func)
        << E->isImplicit();
      return false;
    }
  };
}

bool Sema::checkThisInStaticMemberFunctionType(CXXMethodDecl *Method) {
  TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
  if (!TSInfo)
    return false;

  TypeLoc TL = TSInfo->getTypeLoc();
  FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>();
  if (!ProtoTL)
    return false;

  // C++11 [expr.prim.general]p3:
  //   [The expression this] shall not appear before the optional
  //   cv-qualifier-seq and it shall not appear within the declaration of a
  //   static member function (although its type and value category are defined
  //   within a static member function as they are within a non-static member
  //   function). [ Note: this is because declaration matching does not occur
  //  until the complete declarator is known. - end note ]
  const FunctionProtoType *Proto = ProtoTL.getTypePtr();
  FindCXXThisExpr Finder(*this);

  // If the return type came after the cv-qualifier-seq, check it now.
  if (Proto->hasTrailingReturn() &&
      !Finder.TraverseTypeLoc(ProtoTL.getReturnLoc()))
    return true;

  // Check the exception specification.
  if (checkThisInStaticMemberFunctionExceptionSpec(Method))
    return true;

  return checkThisInStaticMemberFunctionAttributes(Method);
}

bool Sema::checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method) {
  TypeSourceInfo *TSInfo = Method->getTypeSourceInfo();
  if (!TSInfo)
    return false;

  TypeLoc TL = TSInfo->getTypeLoc();
  FunctionProtoTypeLoc ProtoTL = TL.getAs<FunctionProtoTypeLoc>();
  if (!ProtoTL)
    return false;

  const FunctionProtoType *Proto = ProtoTL.getTypePtr();
  FindCXXThisExpr Finder(*this);

  switch (Proto->getExceptionSpecType()) {
  case EST_Unparsed:
  case EST_Uninstantiated:
  case EST_Unevaluated:
  case EST_BasicNoexcept:
  case EST_NoThrow:
  case EST_DynamicNone:
  case EST_MSAny:
  case EST_None:
    break;

  case EST_DependentNoexcept:
  case EST_NoexceptFalse:
  case EST_NoexceptTrue:
    if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
      return true;
    LLVM_FALLTHROUGH;

  case EST_Dynamic:
    for (const auto &E : Proto->exceptions()) {
      if (!Finder.TraverseType(E))
        return true;
    }
    break;
  }

  return false;
}

bool Sema::checkThisInStaticMemberFunctionAttributes(CXXMethodDecl *Method) {
  FindCXXThisExpr Finder(*this);

  // Check attributes.
  for (const auto *A : Method->attrs()) {
    // FIXME: This should be emitted by tblgen.
    Expr *Arg = nullptr;
    ArrayRef<Expr *> Args;
    if (const auto *G = dyn_cast<GuardedByAttr>(A))
      Arg = G->getArg();
    else if (const auto *G = dyn_cast<PtGuardedByAttr>(A))
      Arg = G->getArg();
    else if (const auto *AA = dyn_cast<AcquiredAfterAttr>(A))
      Args = llvm::makeArrayRef(AA->args_begin(), AA->args_size());
    else if (const auto *AB = dyn_cast<AcquiredBeforeAttr>(A))
      Args = llvm::makeArrayRef(AB->args_begin(), AB->args_size());
    else if (const auto *ETLF = dyn_cast<ExclusiveTrylockFunctionAttr>(A)) {
      Arg = ETLF->getSuccessValue();
      Args = llvm::makeArrayRef(ETLF->args_begin(), ETLF->args_size());
    } else if (const auto *STLF = dyn_cast<SharedTrylockFunctionAttr>(A)) {
      Arg = STLF->getSuccessValue();
      Args = llvm::makeArrayRef(STLF->args_begin(), STLF->args_size());
    } else if (const auto *LR = dyn_cast<LockReturnedAttr>(A))
      Arg = LR->getArg();
    else if (const auto *LE = dyn_cast<LocksExcludedAttr>(A))
      Args = llvm::makeArrayRef(LE->args_begin(), LE->args_size());
    else if (const auto *RC = dyn_cast<RequiresCapabilityAttr>(A))
      Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size());
    else if (const auto *AC = dyn_cast<AcquireCapabilityAttr>(A))
      Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size());
    else if (const auto *AC = dyn_cast<TryAcquireCapabilityAttr>(A))
      Args = llvm::makeArrayRef(AC->args_begin(), AC->args_size());
    else if (const auto *RC = dyn_cast<ReleaseCapabilityAttr>(A))
      Args = llvm::makeArrayRef(RC->args_begin(), RC->args_size());

    if (Arg && !Finder.TraverseStmt(Arg))
      return true;

    for (unsigned I = 0, N = Args.size(); I != N; ++I) {
      if (!Finder.TraverseStmt(Args[I]))
        return true;
    }
  }

  return false;
}

void Sema::checkExceptionSpecification(
    bool IsTopLevel, ExceptionSpecificationType EST,
    ArrayRef<ParsedType> DynamicExceptions,
    ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr,
    SmallVectorImpl<QualType> &Exceptions,
    FunctionProtoType::ExceptionSpecInfo &ESI) {
  Exceptions.clear();
  ESI.Type = EST;
  if (EST == EST_Dynamic) {
    Exceptions.reserve(DynamicExceptions.size());
    for (unsigned ei = 0, ee = DynamicExceptions.size(); ei != ee; ++ei) {
      // FIXME: Preserve type source info.
      QualType ET = GetTypeFromParser(DynamicExceptions[ei]);

      if (IsTopLevel) {
        SmallVector<UnexpandedParameterPack, 2> Unexpanded;
        collectUnexpandedParameterPacks(ET, Unexpanded);
        if (!Unexpanded.empty()) {
          DiagnoseUnexpandedParameterPacks(
              DynamicExceptionRanges[ei].getBegin(), UPPC_ExceptionType,
              Unexpanded);
          continue;
        }
      }

      // Check that the type is valid for an exception spec, and
      // drop it if not.
      if (!CheckSpecifiedExceptionType(ET, DynamicExceptionRanges[ei]))
        Exceptions.push_back(ET);
    }
    ESI.Exceptions = Exceptions;
    return;
  }

  if (isComputedNoexcept(EST)) {
    assert((NoexceptExpr->isTypeDependent() ||
            NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
            Context.BoolTy) &&
           "Parser should have made sure that the expression is boolean");
    if (IsTopLevel && DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
      ESI.Type = EST_BasicNoexcept;
      return;
    }

    ESI.NoexceptExpr = NoexceptExpr;
    return;
  }
}

void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
             ExceptionSpecificationType EST,
             SourceRange SpecificationRange,
             ArrayRef<ParsedType> DynamicExceptions,
             ArrayRef<SourceRange> DynamicExceptionRanges,
             Expr *NoexceptExpr) {
  if (!MethodD)
    return;

  // Dig out the method we're referring to.
  if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD))
    MethodD = FunTmpl->getTemplatedDecl();

  CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(MethodD);
  if (!Method)
    return;

  // Check the exception specification.
  llvm::SmallVector<QualType, 4> Exceptions;
  FunctionProtoType::ExceptionSpecInfo ESI;
  checkExceptionSpecification(/*IsTopLevel*/true, EST, DynamicExceptions,
                              DynamicExceptionRanges, NoexceptExpr, Exceptions,
                              ESI);

  // Update the exception specification on the function type.
  Context.adjustExceptionSpec(Method, ESI, /*AsWritten*/true);

  if (Method->isStatic())
    checkThisInStaticMemberFunctionExceptionSpec(Method);

  if (Method->isVirtual()) {
    // Check overrides, which we previously had to delay.
    for (const CXXMethodDecl *O : Method->overridden_methods())
      CheckOverridingFunctionExceptionSpec(Method, O);
  }
}

/// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class.
///
MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record,
                                       SourceLocation DeclStart, Declarator &D,
                                       Expr *BitWidth,
                                       InClassInitStyle InitStyle,
                                       AccessSpecifier AS,
                                       const ParsedAttr &MSPropertyAttr) {
  IdentifierInfo *II = D.getIdentifier();
  if (!II) {
    Diag(DeclStart, diag::err_anonymous_property);
    return nullptr;
  }
  SourceLocation Loc = D.getIdentifierLoc();

  TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
  QualType T = TInfo->getType();
  if (getLangOpts().CPlusPlus) {
    CheckExtraCXXDefaultArguments(D);

    if (DiagnoseUnexpandedParameterPack(D.getIdentifierLoc(), TInfo,
                                        UPPC_DataMemberType)) {
      D.setInvalidType();
      T = Context.IntTy;
      TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
    }
  }

  DiagnoseFunctionSpecifiers(D.getDeclSpec());

  if (D.getDeclSpec().isInlineSpecified())
    Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function)
        << getLangOpts().CPlusPlus17;
  if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
    Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
         diag::err_invalid_thread)
      << DeclSpec::getSpecifierName(TSCS);

  // Check to see if this name was declared as a member previously
  NamedDecl *PrevDecl = nullptr;
  LookupResult Previous(*this, II, Loc, LookupMemberName,
                        ForVisibleRedeclaration);
  LookupName(Previous, S);
  switch (Previous.getResultKind()) {
  case LookupResult::Found:
  case LookupResult::FoundUnresolvedValue:
    PrevDecl = Previous.getAsSingle<NamedDecl>();
    break;

  case LookupResult::FoundOverloaded:
    PrevDecl = Previous.getRepresentativeDecl();
    break;

  case LookupResult::NotFound:
  case LookupResult::NotFoundInCurrentInstantiation:
  case LookupResult::Ambiguous:
    break;
  }

  if (PrevDecl && PrevDecl->isTemplateParameter()) {
    // Maybe we will complain about the shadowed template parameter.
    DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
    // Just pretend that we didn't see the previous declaration.
    PrevDecl = nullptr;
  }

  if (PrevDecl && !isDeclInScope(PrevDecl, Record, S))
    PrevDecl = nullptr;

  SourceLocation TSSL = D.getBeginLoc();
  MSPropertyDecl *NewPD =
      MSPropertyDecl::Create(Context, Record, Loc, II, T, TInfo, TSSL,
                             MSPropertyAttr.getPropertyDataGetter(),
                             MSPropertyAttr.getPropertyDataSetter());
  ProcessDeclAttributes(TUScope, NewPD, D);
  NewPD->setAccess(AS);

  if (NewPD->isInvalidDecl())
    Record->setInvalidDecl();

  if (D.getDeclSpec().isModulePrivateSpecified())
    NewPD->setModulePrivate();

  if (NewPD->isInvalidDecl() && PrevDecl) {
    // Don't introduce NewFD into scope; there's already something
    // with the same name in the same scope.
  } else if (II) {
    PushOnScopeChains(NewPD, S);
  } else
    Record->addDecl(NewPD);

  return NewPD;
}
