//===------ SemaDeclCXX.cpp - Semantic Analysis for C++ Declarations ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  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/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->getLocStart(),
                     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->getLocStart(),
                       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->getLocStart(),
                   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->getLocStart(), 
                   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;

  switch(EST) {
  // If this function can throw any exceptions, make a note of that.
  case EST_MSAny:
  case EST_None:
    ClearExceptions();
    ComputedEST = EST;
    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:
    return;
  // If we're still at noexcept(true) and there's a nothrow() callee,
  // change to that specification.
  case EST_DynamicNone:
    if (ComputedEST == EST_BasicNoexcept)
      ComputedEST = EST_DynamicNone;
    return;
  // Check out noexcept specs.
  case EST_ComputedNoexcept:
  {
    FunctionProtoType::NoexceptResult NR =
        Proto->getNoexceptSpec(Self->Context);
    assert(NR != FunctionProtoType::NR_NoNoexcept &&
           "Must have noexcept result for EST_ComputedNoexcept.");
    assert(NR != FunctionProtoType::NR_Dependent &&
           "Should not generate implicit declarations for dependent cases, "
           "and don't know how to handle them anyway.");
    // noexcept(false) -> no spec on the new function
    if (NR == FunctionProtoType::NR_Throw) {
      ClearExceptions();
      ComputedEST = EST_None;
    }
    // noexcept(true) won't change anything either.
    return;
  }
  default:
    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
      // sufficent, 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.
      // 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)) {
    // 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++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
  // or a for-range-declaration, 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().CPlusPlus1z
                                   ? diag::warn_cxx14_compat_decomp_decl
                                   : diag::ext_decomp_decl)
      << Decomp.getSourceRange();

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

  // C++1z [dcl.dcl]/8:
  //   The decl-specifier-seq shall contain only the type-specifier auto
  //   and cv-qualifiers.
  auto &DS = D.getDeclSpec();
  {
    SmallVector<StringRef, 8> BadSpecifiers;
    SmallVector<SourceLocation, 8> BadSpecifierLocs;
    if (auto SCS = DS.getStorageClassSpec()) {
      BadSpecifiers.push_back(DeclSpec::getSpecifierName(SCS));
      BadSpecifierLocs.push_back(DS.getStorageClassSpecLoc());
    }
    if (auto TSCS = DS.getThreadStorageClassSpec()) {
      BadSpecifiers.push_back(DeclSpec::getSpecifierName(TSCS));
      BadSpecifierLocs.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);
    }
    // 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,
                          ForRedeclaration);
    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, ForRedeclaration);

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

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

  return New;
}

static bool checkSimpleDecomposition(
    Sema &S, ArrayRef<BindingDecl *> Bindings, ValueDecl *Src,
    QualType DecompType, 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,
                                        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::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;

  // FIXME: According to the standard, we're not supposed to diagnose if any
  // of the steps below fail (or if lookup for ::value is ambiguous or otherwise
  // results in an error), but this is subject to a pending CWG issue / NB
  // comment, which says we do diagnose if tuple_size<T> is complete but
  // tuple_size<T>::value is not an ICE.

  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,
                                        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;
    UseMemberGet = !MemberGet.empty();
    S.FilterAcceptableTemplateNames(MemberGet);
  }

  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.ActOnCallExpr(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.ActOnCallExpr(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);
    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 const CXXRecordDecl *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;
  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 RD;
    }

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

    //   ... public base class of E.
    if (BestPath->Access != AS_public) {
      S.Diag(Loc, diag::err_decomp_decl_non_public_base)
        << RD << BaseType;
      for (auto &BS : *BestPath) {
        if (BS.Base->getAccessSpecifier() != AS_public) {
          S.Diag(BS.Base->getLocStart(), diag::note_access_constrained_by_path)
            << (BS.Base->getAccessSpecifier() == AS_protected)
            << (BS.Base->getAccessSpecifierAsWritten() == AS_none);
          break;
        }
      }
      return nullptr;
    }

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

  return ClassWithFields;
}

static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
                                     ValueDecl *Src, QualType DecompType,
                                     const CXXRecordDecl *RD) {
  CXXCastPath BasePath;
  RD = findDecomposableBaseClass(S, Src->getLocation(), RD, BasePath);
  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 public [...] members,
  //   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();
    if (FD->getAccess() != AS_public) {
      S.Diag(Loc, diag::err_decomp_decl_non_public_member) << FD << DecompType;

      // Determine whether the access specifier was explicit.
      bool Implicit = true;
      for (const auto *D : RD->decls()) {
        if (declaresSameEntity(D, FD))
          break;
        if (isa<AccessSpecDecl>(D)) {
          Implicit = false;
          break;
        }
      }

      S.Diag(FD->getLocation(), diag::note_access_natural)
        << (FD->getAccess() == AS_protected) << Implicit;
      return true;
    }

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

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

/// \brief 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;
    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.getLocStart(),
             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;
    const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD);
    if (Method && Method->isVirtual()) {
      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->getLocStart(),
                     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->getLocStart();
      continue;

    default:
      SemaRef.Diag(DS->getLocStart(), 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) {
  // - 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->getLocStart();
      return true;
    }

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

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

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

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

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

    IfStmt *If = cast<IfStmt>(S);
    if (!CheckConstexprFunctionStmt(SemaRef, Dcl, If->getThen(), ReturnStmts,
                                    Cxx1yLoc))
      return false;
    if (If->getElse() &&
        !CheckConstexprFunctionStmt(SemaRef, Dcl, If->getElse(), ReturnStmts,
                                    Cxx1yLoc))
      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->getLocStart();
    for (Stmt *SubStmt : S->children())
      if (SubStmt &&
          !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
                                      Cxx1yLoc))
        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->getLocStart();
    for (Stmt *SubStmt : S->children())
      if (SubStmt &&
          !CheckConstexprFunctionStmt(SemaRef, Dcl, SubStmt, ReturnStmts,
                                      Cxx1yLoc))
        return false;
    return true;

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

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

  SemaRef.Diag(S->getLocStart(), 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) {
  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;
    Diag(Body->getLocStart(), diag::err_constexpr_function_try_block)
      << isa<CXXConstructorDecl>(Dcl);
    return false;
  }

  SmallVector<SourceLocation, 4> ReturnStmts;

  // - its function-body shall be [...] a compound-statement that contains only
  //   [... list of cases ...]
  CompoundStmt *CompBody = cast<CompoundStmt>(Body);
  SourceLocation Cxx1yLoc;
  for (auto *BodyIt : CompBody->body()) {
    if (!CheckConstexprFunctionStmt(*this, Dcl, BodyIt, ReturnStmts, Cxx1yLoc))
      return false;
  }

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

/// 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 *,
                              const CXXScopeSpec *SS) {
  assert(getLangOpts().CPlusPlus && "No class names in C!");

  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())
    return &II == CurDecl->getIdentifier();
  return false;
}

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

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

/// \brief 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");

  // 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.
  if (!Attributes.empty()) {
    for (AttributeList *Attr = Attributes.getList(); Attr;
         Attr = Attr->getNext()) {
      if (Attr->isInvalid() ||
          Attr->getKind() == AttributeList::IgnoredAttribute)
        continue;
      Diag(Attr->getLoc(),
           Attr->getKind() == AttributeList::UnknownAttribute
             ? diag::warn_unknown_attribute_ignored
             : diag::err_base_specifier_attribute)
        << Attr->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;

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

/// \brief 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]->getLocStart(),
           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->isInterface() ||
               KnownBase->getAccessSpecifier() != AS_public)) {
          // The Microsoft extension __interface does not permit bases that
          // are not themselves public interfaces.
          Diag(KnownBase->getLocStart(), diag::err_invalid_base_in_interface)
            << getRecordDiagFromTagKind(RD->getTagKind()) << RD->getName()
            << 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);
  
  for (unsigned idx = 0; idx < NumGoodBases; ++idx) {
    // Check whether this direct base is inaccessible due to ambiguity.
    QualType BaseType = Bases[idx]->getType();
    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]->getLocStart (), 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);
}

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

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

void Sema::BuildBasePathArray(const CXXBasePaths &Paths, 
                              CXXCastPath &BasePathArray) {
  assert(BasePathArray.empty() && "Base path array must be empty!");
  assert(Paths.isRecordingPaths() && "Must record paths!");
  
  const CXXBasePath &Path = Paths.front();
       
  // 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));
}

/// 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);
  assert(DerivationOkay &&
         "Can only be used with a derived-to-base conversion");
  (void)DerivationOkay;
  
  if (!Paths.isAmbiguous(Context.getCanonicalType(Base).getUnqualifiedType())) {
    if (!IgnoreAccess) {
      // Check that the base class can be accessed.
      switch (CheckBaseClassAccess(Loc, Base, Derived, Paths.front(),
                                   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(Paths, *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);
}


/// @brief 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,
                                AttributeList *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->begin_overridden_methods() != MD->end_overridden_methods();
  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>() ||
      isa<CXXDestructorDecl>(MD))
    return;

  SourceLocation Loc = MD->getLocation();
  SourceLocation SpellingLoc = Loc;
  if (getSourceManager().isMacroArgExpansion(Loc))
    SpellingLoc = getSourceManager().getImmediateExpansionRange(Loc).first;
  SpellingLoc = getSourceManager().getSpellingLoc(SpellingLoc);
  if (SpellingLoc.isValid() && getSourceManager().isInSystemHeader(SpellingLoc))
      return;
    
  if (MD->size_overridden_methods() > 0) {
    Diag(MD->getLocation(), diag::warn_function_marked_not_override_overriding)
      << 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 AttributeList *getMSPropertyAttr(AttributeList *list) {
  for (AttributeList *it = list; it != nullptr; it = it->getNext())
    if (it->isDeclspecPropertyAttribute())
      return it;
  return nullptr;
}

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

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

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

  bool isFunc = D.isDeclarationOfFunction();

  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)
      InvalidDecl = (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) ? 0 : 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());
      else
        Diag(D.getIdentifierLoc(), diag::err_member_qualification)
          << Name << SS.getRange();
      
      SS.clear();
    }

    AttributeList *MSPropertyAttr =
      getMSPropertyAttr(D.getDeclSpec().getAttributes().getList());
    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;
    }
  } 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();
    }

    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 (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Member))
      FunTmpl->getTemplatedDecl()->setAccess(AS);
    else if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(Member))
      VarTmpl->getTemplatedDecl()->setAccess(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 unintialized 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->getNumArgs() == 1) {
        if (FunctionDecl *FD = E->getDirectCallee()) {
          if (FD->isInStdNamespace() && FD->getIdentifier() &&
              FD->getIdentifier()->isStr("move")) {
            HandleValue(E->getArg(0), false /*AddressOf*/);
            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

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

/// \brief 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::InitializeMember(FD);
    InitializationKind Kind = FD->getInClassInitStyle() == ICIS_ListInit
        ? InitializationKind::CreateDirectList(InitExpr->getLocStart())
        : InitializationKind::CreateCopy(InitExpr->getLocStart(), 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);
  if (Init.isInvalid()) {
    FD->setInvalidDecl();
    return;
  }

  InitExpr = Init.get();

  FD->setInClassInitializer(InitExpr);
}

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

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

/// \brief 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 = new (Context) ParenListExpr(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 : 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;
  }

private:
  CXXRecordDecl *ClassDecl;
};

}

/// \brief 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. ]
  if (!SS.getScopeRep() && !TemplateTypeTy) {
    // Look for a member, first.
    DeclContext::lookup_result Result = ClassDecl->lookup(MemberOrBase);
    if (!Result.empty()) {
      ValueDecl *Member;
      if ((Member = dyn_cast<FieldDecl>(Result.front())) ||
          (Member = dyn_cast<IndirectFieldDecl>(Result.front()))) {
        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);
  } else if (DS.getTypeSpecType() == TST_decltype) {
    BaseType = BuildDecltypeType(DS.getRepAsExpr(), DS.getTypeSpecTypeLoc());
  } 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;

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

      // If no results were found, try to correct typos.
      TypoCorrection Corr;
      if (R.empty() && BaseType.isNull() &&
          (Corr = CorrectTypo(
               R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
               llvm::make_unique<MemInitializerValidatorCCC>(ClassDecl),
               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->getLocStart(),
                 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);
}

/// Checks a member initializer expression for cases where reference (or
/// pointer) members are bound to by-value parameters (or their addresses).
static void CheckForDanglingReferenceOrPointer(Sema &S, ValueDecl *Member,
                                               Expr *Init,
                                               SourceLocation IdLoc) {
  QualType MemberTy = Member->getType();

  // We only handle pointers and references currently.
  // FIXME: Would this be relevant for ObjC object pointers? Or block pointers?
  if (!MemberTy->isReferenceType() && !MemberTy->isPointerType())
    return;

  const bool IsPointer = MemberTy->isPointerType();
  if (IsPointer) {
    if (const UnaryOperator *Op
          = dyn_cast<UnaryOperator>(Init->IgnoreParenImpCasts())) {
      // The only case we're worried about with pointers requires taking the
      // address.
      if (Op->getOpcode() != UO_AddrOf)
        return;

      Init = Op->getSubExpr();
    } else {
      // We only handle address-of expression initializers for pointers.
      return;
    }
  }

  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init->IgnoreParens())) {
    // We only warn when referring to a non-reference parameter declaration.
    const ParmVarDecl *Parameter = dyn_cast<ParmVarDecl>(DRE->getDecl());
    if (!Parameter || Parameter->getType()->isReferenceType())
      return;

    S.Diag(Init->getExprLoc(),
           IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
                     : diag::warn_bind_ref_member_to_parameter)
      << Member << Parameter << Init->getSourceRange();
  } else {
    // Other initializers are fine.
    return;
  }

  S.Diag(Member->getLocation(), diag::note_ref_or_ptr_member_declared_here)
    << (unsigned)IsPointer;
}

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

    CheckForDanglingReferenceOrPointer(*this, Member, MemberInit.get(), IdLoc);

    // C++11 [class.base.init]p7:
    //   The initialization of each base and member constitutes a
    //   full-expression.
    MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin());
    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)
             : 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());
  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());
  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->getLocStart();
  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->isBitField() && Field->getBitWidthValue(SemaRef.Context) == 0)
      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());
    }

    // When the field we are copying is an array, create index variables for 
    // each dimension of the array. We use these index variables to subscript
    // the source array, and other clients (e.g., CodeGen) will perform the
    // necessary iteration with these index variables.
    SmallVector<VarDecl *, 4> IndexVariables;
    QualType BaseType = Field->getType();
    QualType SizeType = SemaRef.Context.getSizeType();
    bool InitializingArray = false;
    while (const ConstantArrayType *Array
                          = SemaRef.Context.getAsConstantArrayType(BaseType)) {
      InitializingArray = true;
      // Create the iteration variable for this array index.
      IdentifierInfo *IterationVarName = nullptr;
      {
        SmallString<8> Str;
        llvm::raw_svector_ostream OS(Str);
        OS << "__i" << IndexVariables.size();
        IterationVarName = &SemaRef.Context.Idents.get(OS.str());
      }
      VarDecl *IterationVar
        = VarDecl::Create(SemaRef.Context, SemaRef.CurContext, Loc, Loc,
                          IterationVarName, SizeType,
                        SemaRef.Context.getTrivialTypeSourceInfo(SizeType, Loc),
                          SC_None);
      IndexVariables.push_back(IterationVar);
      
      // Create a reference to the iteration variable.
      ExprResult IterationVarRef
        = SemaRef.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
      assert(!IterationVarRef.isInvalid() &&
             "Reference to invented variable cannot fail!");
      IterationVarRef = SemaRef.DefaultLvalueConversion(IterationVarRef.get());
      assert(!IterationVarRef.isInvalid() &&
             "Conversion of invented variable cannot fail!");

      // Subscript the array with this iteration variable.
      CtorArg = SemaRef.CreateBuiltinArraySubscriptExpr(CtorArg.get(), Loc,
                                                        IterationVarRef.get(),
                                                        Loc);
      if (CtorArg.isInvalid())
        return true;

      BaseType = Array->getElementType();
    }

    // The array subscript expression is an lvalue, which is wrong for moving.
    if (Moving && InitializingArray)
      CtorArg = CastForMoving(SemaRef, CtorArg.get());

    // Construct the entity that we will be initializing. For an array, this
    // will be first element in the array, which may require several levels
    // of array-subscript entities. 
    SmallVector<InitializedEntity, 4> Entities;
    Entities.reserve(1 + IndexVariables.size());
    if (Indirect)
      Entities.push_back(InitializedEntity::InitializeMember(Indirect));
    else
      Entities.push_back(InitializedEntity::InitializeMember(Field));
    for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
      Entities.push_back(InitializedEntity::InitializeElement(SemaRef.Context,
                                                              0,
                                                              Entities.back()));
    
    // Direct-initialize to use the copy constructor.
    InitializationKind InitKind =
      InitializationKind::CreateDirect(Loc, SourceLocation(), SourceLocation());
    
    Expr *CtorArgE = CtorArg.getAs<Expr>();
    InitializationSequence InitSeq(SemaRef, Entities.back(), InitKind,
                                   CtorArgE);

    ExprResult MemberInit
      = InitSeq.Perform(SemaRef, Entities.back(), InitKind, 
                        MultiExprArg(&CtorArgE, 1));
    MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
    if (MemberInit.isInvalid())
      return true;

    if (Indirect) {
      assert(IndexVariables.size() == 0 && 
             "Indirect field improperly initialized");
      CXXMemberInit
        = new (SemaRef.Context) CXXCtorInitializer(SemaRef.Context, Indirect, 
                                                   Loc, Loc, 
                                                   MemberInit.getAs<Expr>(), 
                                                   Loc);
    } else
      CXXMemberInit = CXXCtorInitializer::Create(SemaRef.Context, Field, Loc, 
                                                 Loc, MemberInit.getAs<Expr>(), 
                                                 Loc,
                                                 IndexVariables.data(),
                                                 IndexVariables.size());
    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)
                : InitializedEntity::InitializeMember(Field);
    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 (SemaRef.getLangOpts().ObjCAutoRefCount &&
      FieldBaseElementType->isObjCRetainableType() &&
      FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_None &&
      FieldBaseElementType.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) {
    // ARC:
    //   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();
  }

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

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

  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())
      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.getLocStart(), Dtor,
                          PDiag(diag::err_access_dtor_base)
                            << Base.getType()
                            << Base.getSourceRange(),
                          Context.getTypeDeclType(ClassDecl));
    
    MarkFunctionReferenced(Location, Dtor);
    DiagnoseUseOfDecl(Dtor, Location);
  }
  
  // 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 ReferenceDllExportedMethods(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;

  for (Decl *Member : Class->decls()) {
    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 accross libraries.
        DiagnosticErrorTrap Trap(S.Diags);
        S.MarkFunctionReferenced(Class->getLocation(), MD);
        if (Trap.hasErrorOccurred()) {
          S.Diag(ClassAttr->getLocation(), diag::note_due_to_dllexported_class)
              << Class->getName() << !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));
      }
    }
  }
}

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

  TemplateSpecializationKind TSK = Class->getTemplateSpecializationKind();

  // Ignore explicit dllexport on explicit class template instantiation declarations.
  if (ClassExported && !ClassAttr->isInherited() &&
      TSK == TSK_ExplicitInstantiationDeclaration) {
    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.
        if (!Context.getTargetInfo().getCXXABI().isMicrosoft() &&
            !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())
          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;
      }
    }

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

    if (!getDLLAttr(Member)) {
      auto *NewAttr =
          cast<InheritableAttr>(ClassAttr->clone(getASTContext()));
      NewAttr->setInherited(true);
      Member->addAttr(NewAttr);
    }
  }

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

/// \brief 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 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.");
  }
}

/// \brief 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;
      if ((isa<FieldDecl>(D) && Record->hasUserDeclaredConstructor()) ||
          isa<IndirectFieldDecl>(D)) {
        Diag(D->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);
    }
  }

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

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

/// 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 || !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
computeImplicitExceptionSpec(Sema &S, SourceLocation Loc, CXXMethodDecl *MD) {
  switch (S.getSpecialMember(MD)) {
  case Sema::CXXDefaultConstructor:
    return S.ComputeDefaultedDefaultCtorExceptionSpec(Loc, MD);
  case Sema::CXXCopyConstructor:
    return S.ComputeDefaultedCopyCtorExceptionSpec(MD);
  case Sema::CXXCopyAssignment:
    return S.ComputeDefaultedCopyAssignmentExceptionSpec(MD);
  case Sema::CXXMoveConstructor:
    return S.ComputeDefaultedMoveCtorExceptionSpec(MD);
  case Sema::CXXMoveAssignment:
    return S.ComputeDefaultedMoveAssignmentExceptionSpec(MD);
  case Sema::CXXDestructor:
    return S.ComputeDefaultedDtorExceptionSpec(MD);
  case Sema::CXXInvalid:
    break;
  }
  assert(cast<CXXConstructorDecl>(MD)->getInheritedConstructor() &&
         "only special members have implicit exception specs");
  return S.ComputeInheritingCtorExceptionSpec(Loc,
                                              cast<CXXConstructorDecl>(MD));
}

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 ESI = computeImplicitExceptionSpec(*this, Loc, MD).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.
  unsigned ExpectedParams = 1;
  if (CSM == CXXDefaultConstructor || CSM == CXXDestructor)
    ExpectedParams = 0;
  if (MD->getNumParams() != ExpectedParams) {
    // This also 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()) {
    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 ExpectedReturnType =
        Context.getLValueReferenceType(Context.getTypeDeclType(RD));
    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->getTypeQuals()) {
      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()) {
      Diag(MD->getLocation(),
           diag::err_defaulted_special_member_volatile_param) << CSM;
      HadError = true;
    }

    if (HasConstParam && !CanHaveConstParam) {
      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.
      } 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.
  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->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM;
    // FIXME: Explain why the special member can't be constexpr.
    HadError = true;
  }

  //   and may have an explicit exception-specification only if it is compatible
  //   with the exception-specification on the implicit declaration.
  if (Type->hasExceptionSpec()) {
    // Delay the check if this is the first declaration of the special member,
    // since we may not have parsed some necessary in-class initializers yet.
    if (First) {
      // If the exception specification needs to be instantiated, do so now,
      // before we clobber it with an EST_Unevaluated specification below.
      if (Type->getExceptionSpecType() == EST_Uninstantiated) {
        InstantiateExceptionSpec(MD->getLocStart(), MD);
        Type = MD->getType()->getAs<FunctionProtoType>();
      }
      DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type));
    } else
      CheckExplicitlyDefaultedMemberExceptionSpec(MD, Type);
  }

  //   If a function is explicitly defaulted on its first declaration,
  if (First) {
    //  -- it is implicitly considered to be constexpr if the implicit
    //     definition would be,
    MD->setConstexpr(Constexpr);

    //  -- it is implicitly considered to have the same exception-specification
    //     as if it had been implicitly declared,
    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 (ShouldDeleteSpecialMember(MD, CSM)) {
    if (First) {
      SetDeclDeleted(MD, MD->getLocation());
    } 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;
      ShouldDeleteSpecialMember(MD, CSM, nullptr, /*Diagnose*/true);
      HadError = true;
    }
  }

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

/// Check whether the exception specification provided for an
/// explicitly-defaulted special member matches the exception specification
/// that would have been generated for an implicit special member, per
/// C++11 [dcl.fct.def.default]p2.
void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
    CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) {
  // If the exception specification was explicitly specified but hadn't been
  // parsed when the method was defaulted, grab it now.
  if (SpecifiedType->getExceptionSpecType() == EST_Unparsed)
    SpecifiedType =
        MD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>();

  // Compute the implicit exception specification.
  CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false,
                                                       /*IsCXXMethod=*/true);
  FunctionProtoType::ExtProtoInfo EPI(CC);
  EPI.ExceptionSpec = computeImplicitExceptionSpec(*this, MD->getLocation(), MD)
                          .getExceptionSpec();
  const FunctionProtoType *ImplicitType = cast<FunctionProtoType>(
    Context.getFunctionType(Context.VoidTy, None, EPI));

  // Ensure that it matches.
  CheckEquivalentExceptionSpec(
    PDiag(diag::err_incorrect_defaulted_exception_spec)
      << getSpecialMember(MD), PDiag(),
    ImplicitType, SourceLocation(),
    SpecifiedType, MD->getLocation());
}

void Sema::CheckDelayedMemberExceptionSpecs() {
  decltype(DelayedExceptionSpecChecks) Checks;
  decltype(DelayedDefaultedMemberExceptionSpecs) Specs;

  std::swap(Checks, DelayedExceptionSpecChecks);
  std::swap(Specs, DelayedDefaultedMemberExceptionSpecs);

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

  // Check that any explicitly-defaulted methods have exception specifications
  // compatible with their implicit exception specifications.
  for (auto &Spec : Specs)
    CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second);
}

namespace {
struct SpecialMemberDeletionInfo {
  Sema &S;
  CXXMethodDecl *MD;
  Sema::CXXSpecialMember CSM;
  Sema::InheritedConstructorInfo *ICI;
  bool Diagnose;

  // Properties of the special member, computed for convenience.
  bool IsConstructor, IsAssignment, IsMove, ConstArg;
  SourceLocation Loc;

  bool AllFieldsAreConst;

  SpecialMemberDeletionInfo(Sema &S, CXXMethodDecl *MD,
                            Sema::CXXSpecialMember CSM,
                            Sema::InheritedConstructorInfo *ICI, bool Diagnose)
      : S(S), MD(MD), CSM(CSM), ICI(ICI), Diagnose(Diagnose),
        IsConstructor(false), IsAssignment(false), IsMove(false),
        ConstArg(false), Loc(MD->getLocation()), AllFieldsAreConst(true) {
    switch (CSM) {
      case Sema::CXXDefaultConstructor:
      case Sema::CXXCopyConstructor:
        IsConstructor = true;
        break;
      case Sema::CXXMoveConstructor:
        IsConstructor = true;
        IsMove = true;
        break;
      case Sema::CXXCopyAssignment:
        IsAssignment = true;
        break;
      case Sema::CXXMoveAssignment:
        IsAssignment = true;
        IsMove = 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();
    }
  }

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

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

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

  typedef llvm::PointerUnion<CXXBaseSpecifier*, FieldDecl*> Subobject;

  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;
    } else {
      CXXBaseSpecifier *Base = Subobj.get<CXXBaseSpecifier*>();
      S.Diag(Base->getLocStart(),
             diag::note_deleted_special_member_class_subobject)
        << getEffectiveCSM() << MD->getParent() << /*IsField*/false
        << Base->getType() << DiagKind << IsDtorCallInCtor;
    }

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

/// 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.
  if (ICI) {
    assert(CSM == Sema::CXXDefaultConstructor);
    auto *BaseCtor =
        ICI->findConstructorForBase(BaseClass, cast<CXXConstructorDecl>(MD)
                                                   ->getInheritedConstructor()
                                                   .getConstructor())
            .first;
    if (BaseCtor) {
      if (BaseCtor->isDeleted() && Diagnose) {
        S.Diag(Base->getLocStart(),
               diag::note_deleted_special_member_class_subobject)
          << getEffectiveCSM() << MD->getParent() << /*IsField*/false
          << Base->getType() << /*Deleted*/1 << /*IsDtorCallInCtor*/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 (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 (!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.
  if (RD->isLambda() &&
      (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, a user-declared move only causes the deletion of the
    // corresponding copy operation, not both copy operations.
    if (RD->hasUserDeclaredMoveConstructor() &&
        (!getLangOpts().MSVCCompat || 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() &&
               (!getLangOpts().MSVCCompat || 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);

  for (auto &BI : RD->bases())
    if ((SMI.IsAssignment || !BI.isVirtual()) &&
        SMI.shouldDeleteForBase(&BI))
      return true;

  // Per DR1611, do not consider virtual bases of constructors of abstract
  // classes, since we are not going to construct them. For assignment
  // operators, we only assign (and thus only consider) direct bases.
  if ((!RD->isAbstract() || !SMI.IsConstructor) && !SMI.IsAssignment) {
    for (auto &BI : RD->vbases())
      if (SMI.shouldDeleteForBase(&BI))
        return true;
  }

  for (auto *FI : RD->fields())
    if (!FI->isInvalidDecl() && !FI->isUnnamedBitfield() &&
        SMI.shouldDeleteForField(FI))
      return true;

  if (SMI.shouldDeleteForAllConstMembers())
    return true;

  if (getLangOpts().CUDA) {
    // We should delete the special member in CUDA mode if target inference
    // failed.
    return inferCUDATargetForImplicitSpecialMember(RD, CSM, 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.
static bool findTrivialSpecialMember(Sema &S, CXXRecordDecl *RD,
                                     Sema::CXXSpecialMember CSM, unsigned Quals,
                                     bool ConstRHS, 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())
      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()) {
      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();
    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,
                                      bool Diagnose) {
  CXXRecordDecl *SubRD = SubType->getAsCXXRecordDecl();
  if (!SubRD)
    return true;

  CXXMethodDecl *Selected;
  if (findTrivialSpecialMember(S, SubRD, CSM, SubType.getCVRQualifiers(),
                               ConstRHS, 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, 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, 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, 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 (S.getLangOpts().ObjCAutoRefCount &&
        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, 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, /*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,
                                  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.getLocStart(), BI.getType(),
                                   ConstArg, CSM, TSK_BaseClass, 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, 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.getLocStart(), 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->getLocStart();
        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 overriden 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 (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
                                        E = MD->end_overridden_methods();
         I != E; ++I)
      if (CheckMostOverridenMethods(*I, 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

/// \brief 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());
  for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
                                      E = MD->end_overridden_methods();
       I != E; ++I)
    AddMostOverridenMethods(*I, Methods);
}

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

/// \brief 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::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
                                             Decl *TagDecl,
                                             SourceLocation LBrac,
                                             SourceLocation RBrac,
                                             AttributeList *AttrList) {
  if (!TagDecl)
    return;

  AdjustDeclIfTemplate(TagDecl);

  for (const AttributeList* l = AttrList; l; l = l->getNext()) {
    if (l->getKind() != AttributeList::AT_Visibility)
      continue;
    l->setInvalid();
    Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) <<
      l->getName();
  }

  ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef(
              // strict aliasing violation!
              reinterpret_cast<Decl**>(FieldCollector->getCurFields()),
              FieldCollector->getCurNumFields()), LBrac, RBrac, AttrList);

  CheckCompletedCXXClass(
                        dyn_cast_or_null<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()) {
    ++ASTContext::NumImplicitDefaultConstructors;

    if (ClassDecl->hasInheritedConstructor())
      DeclareImplicitDefaultConstructor(ClassDecl);
  }

  if (ClassDecl->needsImplicitCopyConstructor()) {
    ++ASTContext::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);
  }

  if (getLangOpts().CPlusPlus11 && ClassDecl->needsImplicitMoveConstructor()) {
    ++ASTContext::NumImplicitMoveConstructors;

    if (ClassDecl->needsOverloadResolutionForMoveConstructor() ||
        ClassDecl->hasInheritedConstructor())
      DeclareImplicitMoveConstructor(ClassDecl);
  }

  if (ClassDecl->needsImplicitCopyAssignment()) {
    ++ASTContext::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()) {
    ++ASTContext::NumImplicitMoveAssignmentOperators;

    // Likewise for the move assignment operator.
    if (ClassDecl->isDynamicClass() ||
        ClassDecl->needsOverloadResolutionForMoveAssignment() ||
        ClassDecl->hasInheritedAssignment())
      DeclareImplicitMoveAssignment(ClassDecl);
  }

  if (ClassDecl->needsImplicitDestructor()) {
    ++ASTContext::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.TypeQuals != 0) {
    if (FTI.TypeQuals & Qualifiers::Const)
      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
        << "const" << SourceRange(D.getIdentifierLoc());
    if (FTI.TypeQuals & Qualifiers::Volatile)
      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
        << "volatile" << SourceRange(D.getIdentifierLoc());
    if (FTI.TypeQuals & Qualifiers::Restrict)
      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_constructor)
        << "restrict" << SourceRange(D.getIdentifierLoc());
    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 = 0;
  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)) {
      MarkFunctionReferenced(Loc, OperatorDelete);
      Destructor->setOperatorDelete(OperatorDelete);
    }
  }
  
  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.TypeQuals != 0 && !D.isInvalidType()) {
    if (FTI.TypeQuals & Qualifiers::Const)
      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
        << "const" << SourceRange(D.getIdentifierLoc());
    if (FTI.TypeQuals & Qualifiers::Volatile)
      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
        << "volatile" << SourceRange(D.getIdentifierLoc());
    if (FTI.TypeQuals & Qualifiers::Restrict)
      Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_destructor)
        << "restrict" << SourceRange(D.getIdentifierLoc());
    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 = 0;
  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);

  if (D.getDeclSpec().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(D.getDeclSpec().getTypeSpecTypeLoc())
      << SourceRange(D.getIdentifierLoc());
    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;
        }
        // Fall through.
      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().getLocEnd());
        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 (D.getDeclSpec().isExplicitSpecified())
    Diag(D.getDeclSpec().getExplicitSpecLoc(),
         getLangOpts().CPlusPlus11 ?
           diag::warn_cxx98_compat_explicit_conversion_functions :
           diag::ext_explicit_conversion_functions)
      << SourceRange(D.getDeclSpec().getExplicitSpecLoc());
}

/// 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 Handling
//===----------------------------------------------------------------------===//

/// \brief 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,
                                   AttributeList *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, ForRedeclaration);
    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);

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

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

/// \brief 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 CXXConstructorDecl* 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);
}

/// \brief 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 : public CorrectionCandidateCallback {
public:
  bool ValidateCandidate(const TypoCorrection &candidate) override {
    if (NamedDecl *ND = candidate.getCorrectionDecl())
      return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
    return false;
  }
};

}

static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,
                                       CXXScopeSpec &SS,
                                       SourceLocation IdentLoc,
                                       IdentifierInfo *Ident) {
  R.clear();
  if (TypoCorrection Corrected =
          S.CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), Sc, &SS,
                        llvm::make_unique<NamespaceValidatorCCC>(),
                        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,
                                          AttributeList *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 = cast<DeclContext>(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,
                                  bool HasUsingKeyword,
                                  SourceLocation UsingLoc,
                                  CXXScopeSpec &SS,
                                  UnqualifiedId &Name,
                                  AttributeList *AttrList,
                                  bool HasTypenameKeyword,
                                  SourceLocation TypenameLoc) {
  assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");

  switch (Name.getKind()) {
  case UnqualifiedId::IK_ImplicitSelfParam:
  case UnqualifiedId::IK_Identifier:
  case UnqualifiedId::IK_OperatorFunctionId:
  case UnqualifiedId::IK_LiteralOperatorId:
  case UnqualifiedId::IK_ConversionFunctionId:
    break;
      
  case UnqualifiedId::IK_ConstructorName:
  case UnqualifiedId::IK_ConstructorTemplateId:
    // C++11 inheriting constructors.
    Diag(Name.getLocStart(),
         getLangOpts().CPlusPlus11 ?
           diag::warn_cxx98_compat_using_decl_constructor :
           diag::err_using_decl_constructor)
      << SS.getRange();

    if (getLangOpts().CPlusPlus11) break;

    return nullptr;

  case UnqualifiedId::IK_DestructorName:
    Diag(Name.getLocStart(), diag::err_using_decl_destructor)
      << SS.getRange();
    return nullptr;

  case UnqualifiedId::IK_TemplateId:
    Diag(Name.getLocStart(), diag::err_using_decl_template_id)
      << SourceRange(Name.TemplateId->LAngleLoc, Name.TemplateId->RAngleLoc);
    return nullptr;
  }

  DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name);
  DeclarationName TargetName = TargetNameInfo.getName();
  if (!TargetName)
    return nullptr;

  // Warn about access declarations.
  if (!HasUsingKeyword) {
    Diag(Name.getLocStart(),
         getLangOpts().CPlusPlus11 ? diag::err_access_decl
                                   : diag::warn_access_decl_deprecated)
      << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using ");
  }

  if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) ||
      DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration))
    return nullptr;

  NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
                                        TargetNameInfo, AttrList,
                                        /* IsInstantiation */ false,
                                        HasTypenameKeyword, TypenameLoc);
  if (UD)
    PushOnScopeChains(UD, S, /*AddToContext*/ false);

  return UD;
}

/// \brief 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);
        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);
      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))
      continue;

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

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,
                                       CXXScopeSpec &SS,
                                       DeclarationNameInfo NameInfo,
                                       AttributeList *AttrList,
                                       bool IsInstantiation,
                                       bool HasTypenameKeyword,
                                       SourceLocation TypenameLoc) {
  assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
  SourceLocation IdentLoc = NameInfo.getLoc();
  assert(IdentLoc.isValid() && "Invalid TargetName location.");

  // FIXME: We ignore attributes for now.

  if (SS.isEmpty()) {
    Diag(IdentLoc, diag::err_using_requires_qualname);
    return nullptr;
  }

  // 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,
                        ForRedeclaration);
  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");
    assert(CurContext->isRecord() && "scope not record in instantiation");
    LookupQualifiedName(Previous, CurContext);
  }

  // Check for invalid redeclarations.
  if (CheckUsingDeclRedeclaration(UsingLoc, HasTypenameKeyword,
                                  SS, IdentLoc, Previous))
    return nullptr;

  // Check for bad qualifiers.
  if (CheckUsingDeclQualifier(UsingLoc, SS, NameInfo, IdentLoc))
    return nullptr;

  DeclContext *LookupContext = computeDeclContext(SS);
  NamedDecl *D;
  NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context);
  if (!LookupContext) {
    if (HasTypenameKeyword) {
      // FIXME: not all declaration name kinds are legal here
      D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
                                              UsingLoc, TypenameLoc,
                                              QualifierLoc,
                                              IdentLoc, NameInfo.getName());
    } else {
      D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, 
                                           QualifierLoc, NameInfo);
    }
    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) {
    if (TypoCorrection Corrected = CorrectTypo(
            R.getLookupNameInfo(), R.getLookupKind(), S, &SS,
            llvm::make_unique<UsingValidatorCCC>(
                HasTypenameKeyword, IsInstantiation, SS.getScopeRep(),
                dyn_cast<CXXRecordDecl>(CurContext)),
            CTK_ErrorRecovery)) {
      // We reject any correction for which ND would be NULL.
      NamedDecl *ND = Corrected.getCorrectionDecl();

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

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

  NestedNameSpecifier *Qual = SS.getScopeRep();

  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,
                                   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 must be a
    // dependent class scope.
    if (!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.getLocEnd());
          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, everything is known to be fine.
    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,
                                  AttributeList *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, ForRedeclaration);
  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 == UnqualifiedId::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);

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

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

Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc,
                                               CXXMethodDecl *MD) {
  CXXRecordDecl *ClassDecl = MD->getParent();

  // C++ [except.spec]p14:
  //   An implicitly declared special member function (Clause 12) shall have an 
  //   exception-specification. [...]
  ImplicitExceptionSpecification ExceptSpec(*this);
  if (ClassDecl->isInvalidDecl())
    return ExceptSpec;

  // Direct base-class constructors.
  for (const auto &B : ClassDecl->bases()) {
    if (B.isVirtual()) // Handled below.
      continue;
    
    if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
      CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
      // If this is a deleted function, add it anyway. This might be conformant
      // with the standard. This might not. I'm not sure. It might not matter.
      if (Constructor)
        ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
    }
  }

  // Virtual base-class constructors.
  for (const auto &B : ClassDecl->vbases()) {
    if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
      CXXConstructorDecl *Constructor = LookupDefaultConstructor(BaseClassDecl);
      // If this is a deleted function, add it anyway. This might be conformant
      // with the standard. This might not. I'm not sure. It might not matter.
      if (Constructor)
        ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
    }
  }

  // Field constructors.
  for (const auto *F : ClassDecl->fields()) {
    if (F->hasInClassInitializer()) {
      if (Expr *E = F->getInClassInitializer())
        ExceptSpec.CalledExpr(E);
    } else if (const RecordType *RecordTy
              = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
      CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
      CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl);
      // If this is a deleted function, add it anyway. This might be conformant
      // with the standard. This might not. I'm not sure. It might not matter.
      // In particular, the problem is that this function never gets called. It
      // might just be ill-formed because this function attempts to refer to
      // a deleted function here.
      if (Constructor)
        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
    }
  }

  return ExceptSpec;
}

Sema::ImplicitExceptionSpecification
Sema::ComputeInheritingCtorExceptionSpec(SourceLocation Loc,
                                         CXXConstructorDecl *CD) {
  CXXRecordDecl *ClassDecl = CD->getParent();

  // C++ [except.spec]p14:
  //   An inheriting constructor [...] shall have an exception-specification. [...]
  ImplicitExceptionSpecification ExceptSpec(*this);
  if (ClassDecl->isInvalidDecl())
    return ExceptSpec;

  auto Inherited = CD->getInheritedConstructor();
  InheritedConstructorInfo ICI(*this, Loc, Inherited.getShadowDecl());

  // Direct and virtual base-class constructors.
  for (bool VBase : {false, true}) {
    for (CXXBaseSpecifier &B :
         VBase ? ClassDecl->vbases() : ClassDecl->bases()) {
      // Don't visit direct vbases twice.
      if (B.isVirtual() != VBase)
        continue;

      CXXRecordDecl *BaseClass = B.getType()->getAsCXXRecordDecl();
      if (!BaseClass)
        continue;

      CXXConstructorDecl *Constructor =
          ICI.findConstructorForBase(BaseClass, Inherited.getConstructor())
              .first;
      if (!Constructor)
        Constructor = LookupDefaultConstructor(BaseClass);
      if (Constructor)
        ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
    }
  }

  // Field constructors.
  for (const auto *F : ClassDecl->fields()) {
    if (F->hasInClassInitializer()) {
      if (Expr *E = F->getInClassInitializer())
        ExceptSpec.CalledExpr(E);
    } else if (const RecordType *RecordTy
              = Context.getBaseElementType(F->getType())->getAs<RecordType>()) {
      CXXRecordDecl *FieldRecDecl = cast<CXXRecordDecl>(RecordTy->getDecl());
      CXXConstructorDecl *Constructor = LookupDefaultConstructor(FieldRecDecl);
      if (Constructor)
        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
    }
  }

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

    // FIXME: Register a note to be produced if we encounter an error while
    // declaring the special member.
  }
  ~DeclaringSpecialMember() {
    if (!WasAlreadyBeingDeclared)
      S.SpecialMembersBeingDeclared.erase(D);
  }

  /// \brief 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,
                 ForRedeclaration);
  for (auto *D : FD->getParent()->lookup(Name))
    if (auto *Acceptable = R.getAcceptableDecl(D))
      R.addDecl(Acceptable);
  R.resolveKind();
  R.suppressDiagnostics();

  CheckFunctionDeclaration(S, FD, R, /*IsExplicitSpecialization*/false);
}

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, /*isExplicit=*/false, /*isInline=*/true,
      /*isImplicitlyDeclared=*/true, Constexpr);
  DefaultCon->setAccess(AS_public);
  DefaultCon->setDefaulted();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXDefaultConstructor,
                                            DefaultCon,
                                            /* ConstRHS */ false,
                                            /* Diagnose */ false);
  }

  // Build an exception specification pointing back at this constructor.
  FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, DefaultCon);
  DefaultCon->setType(Context.getFunctionType(Context.VoidTy, None, EPI));

  // 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.
  ++ASTContext::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");

  CXXRecordDecl *ClassDecl = Constructor->getParent();
  assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");

  SynthesizedFunctionScope Scope(*this, Constructor);
  DiagnosticErrorTrap Trap(Diags);
  if (SetCtorInitializers(Constructor, /*AnyErrors=*/false) ||
      Trap.hasErrorOccurred()) {
    Diag(CurrentLocation, diag::note_member_synthesized_at) 
      << CXXDefaultConstructor << Context.getTagDeclType(ClassDecl);
    Constructor->setInvalidDecl();
    return;
  }

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       Constructor->getType()->castAs<FunctionProtoType>());

  SourceLocation Loc = Constructor->getLocEnd().isValid()
                           ? Constructor->getLocEnd()
                           : Constructor->getLocation();
  Constructor->setBody(new (Context) CompoundStmt(Loc));

  Constructor->markUsed(Context);
  MarkVTableUsed(CurrentLocation, ClassDecl);

  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->isExplicit(), /*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->isInvalidDecl())
    return;

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

  // Initializations are performed "as if by a defaulted default constructor",
  // so enter the appropriate scope.
  SynthesizedFunctionScope Scope(*this, Constructor);
  DiagnosticErrorTrap Trap(Diags);

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

  bool HadError = SetCtorInitializers(Constructor, /*AnyErrors*/false, Inits);
  if (HadError || Trap.hasErrorOccurred()) {
    Diag(CurrentLocation, diag::note_inhctor_synthesized_at) << RD;
    Constructor->setInvalidDecl();
    return;
  }

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       Constructor->getType()->castAs<FunctionProtoType>());

  Constructor->setBody(new (Context) CompoundStmt(InitLoc));

  Constructor->markUsed(Context);
  MarkVTableUsed(CurrentLocation, ClassDecl);

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Constructor);
  }

  DiagnoseUninitializedFields(*this, Constructor);
}

Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD) {
  CXXRecordDecl *ClassDecl = MD->getParent();

  // C++ [except.spec]p14: 
  //   An implicitly declared special member function (Clause 12) shall have 
  //   an exception-specification.
  ImplicitExceptionSpecification ExceptSpec(*this);
  if (ClassDecl->isInvalidDecl())
    return ExceptSpec;

  // Direct base-class destructors.
  for (const auto &B : ClassDecl->bases()) {
    if (B.isVirtual()) // Handled below.
      continue;
    
    if (const RecordType *BaseType = B.getType()->getAs<RecordType>())
      ExceptSpec.CalledDecl(B.getLocStart(),
                   LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
  }

  // Virtual base-class destructors.
  for (const auto &B : ClassDecl->vbases()) {
    if (const RecordType *BaseType = B.getType()->getAs<RecordType>())
      ExceptSpec.CalledDecl(B.getLocStart(),
                  LookupDestructor(cast<CXXRecordDecl>(BaseType->getDecl())));
  }

  // Field destructors.
  for (const auto *F : ClassDecl->fields()) {
    if (const RecordType *RecordTy
        = Context.getBaseElementType(F->getType())->getAs<RecordType>())
      ExceptSpec.CalledDecl(F->getLocation(),
                  LookupDestructor(cast<CXXRecordDecl>(RecordTy->getDecl())));
  }

  return ExceptSpec;
}

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

  // Build an exception specification pointing back at this destructor.
  FunctionProtoType::ExtProtoInfo EPI = getImplicitMethodEPI(*this, Destructor);
  Destructor->setType(Context.getFunctionType(Context.VoidTy, None, EPI));

  // We don't need to use SpecialMemberIsTrivial here; triviality for
  // destructors is easy to compute.
  Destructor->setTrivial(ClassDecl->hasTrivialDestructor());

  // Note that we have declared this destructor.
  ++ASTContext::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");
  CXXRecordDecl *ClassDecl = Destructor->getParent();
  assert(ClassDecl && "DefineImplicitDestructor - invalid destructor");

  if (Destructor->isInvalidDecl())
    return;

  SynthesizedFunctionScope Scope(*this, Destructor);

  DiagnosticErrorTrap Trap(Diags);
  MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(),
                                         Destructor->getParent());

  if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) {
    Diag(CurrentLocation, diag::note_member_synthesized_at) 
      << CXXDestructor << Context.getTagDeclType(ClassDecl);

    Destructor->setInvalidDecl();
    return;
  }

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       Destructor->getType()->castAs<FunctionProtoType>());

  SourceLocation Loc = Destructor->getLocEnd().isValid()
                           ? Destructor->getLocEnd()
                           : Destructor->getLocation();
  Destructor->setBody(new (Context) CompoundStmt(Loc));
  Destructor->markUsed(Context);
  MarkVTableUsed(CurrentLocation, ClassDecl);

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Destructor);
  }
}

/// \brief 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()) {
      DelayedDefaultedMemberExceptionSpecs.clear();
      DelayedExceptionSpecChecks.clear();
      return;
    }
  }
}

static void getDefaultArgExprsForConstructors(Sema &S, CXXRecordDecl *Class) {
  // Don't do anything for template patterns.
  if (Class->getDescribedClassTemplate())
    return;

  CallingConv ExpectedCallingConv = S.Context.getDefaultCallingConvention(
      /*IsVariadic=*/false, /*IsCXXMethod=*/true);

  CXXConstructorDecl *LastExportedDefaultCtor = nullptr;
  for (Decl *Member : Class->decls()) {
    auto *CD = dyn_cast<CXXConstructorDecl>(Member);
    if (!CD) {
      // Recurse on nested classes.
      if (auto *NestedRD = dyn_cast<CXXRecordDecl>(Member))
        getDefaultArgExprsForConstructors(S, NestedRD);
      continue;
    } else if (!CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>()) {
      continue;
    }

    CallingConv ActualCallingConv =
        CD->getType()->getAs<FunctionProtoType>()->getCallConv();

    // Skip default constructors with typical calling conventions and no default
    // arguments.
    unsigned NumParams = CD->getNumParams();
    if (ExpectedCallingConv == ActualCallingConv && NumParams == 0)
      continue;

    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;

    for (unsigned I = 0; I != NumParams; ++I) {
      // Skip any default arguments that we've already instantiated.
      if (S.Context.getDefaultArgExprForConstructor(CD, I))
        continue;

      Expr *DefaultArg = S.BuildCXXDefaultArgExpr(Class->getLocation(), CD,
                                                  CD->getParamDecl(I)).get();
      S.DiscardCleanupsInEvaluationContext();
      S.Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);
    }
  }
}

void Sema::ActOnFinishCXXNonNestedClass(Decl *D) {
  auto *RD = dyn_cast<CXXRecordDecl>(D);

  // Default constructors that are annotated with __declspec(dllexport) which
  // have default arguments or don't use the standard calling convention are
  // wrapped with a thunk called the default constructor closure.
  if (RD && Context.getTargetInfo().getCXXABI().isMicrosoft())
    getDefaultArgExprsForConstructors(*this, RD);

  referenceDLLExportedClassMethods();
}

void Sema::referenceDLLExportedClassMethods() {
  if (!DelayedDllExportClasses.empty()) {
    // Calling ReferenceDllExportedMethods 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)
      ReferenceDllExportedMethods(*this, Class);
  }
}

void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
                                         CXXDestructorDecl *Destructor) {
  assert(getLangOpts().CPlusPlus11 &&
         "adjusting dtor exception specs was introduced in c++11");

  // 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 {
/// \brief 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);
  Expr *To = ToB.build(S, Loc);
  To = new (S.Context) UnaryOperator(To, UO_AddrOf,
                       S.Context.getPointerType(To->getType()),
                       VK_RValue, OK_Ordinary, Loc);

  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.ActOnCallExpr(/*Scope=*/nullptr, MemCpyRef.get(),
                                    Loc, CallArgs, Loc);

  assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
  return Call.getAs<Stmt>();
}

/// \brief 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, false);

  // Create the pre-increment of the iteration variable.
  Expr *Increment
    = new (S.Context) UnaryOperator(IterationVarRef.build(S, Loc), UO_PreInc,
                                    SizeType, VK_LValue, OK_Ordinary, Loc);

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

Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD) {
  CXXRecordDecl *ClassDecl = MD->getParent();

  ImplicitExceptionSpecification ExceptSpec(*this);
  if (ClassDecl->isInvalidDecl())
    return ExceptSpec;

  const FunctionProtoType *T = MD->getType()->castAs<FunctionProtoType>();
  assert(T->getNumParams() == 1 && "not a copy assignment op");
  unsigned ArgQuals =
      T->getParamType(0).getNonReferenceType().getCVRQualifiers();

  // C++ [except.spec]p14:
  //   An implicitly declared special member function (Clause 12) shall have an
  //   exception-specification. [...]

  // It is unspecified whether or not an implicit copy assignment operator
  // attempts to deduplicate calls to assignment operators of virtual bases are
  // made. As such, this exception specification is effectively unspecified.
  // Based on a similar decision made for constness in C++0x, we're erring on
  // the side of assuming such calls to be made regardless of whether they
  // actually happen.
  for (const auto &Base : ClassDecl->bases()) {
    if (Base.isVirtual())
      continue;

    CXXRecordDecl *BaseClassDecl
      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
    if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
                                                            ArgQuals, false, 0))
      ExceptSpec.CalledDecl(Base.getLocStart(), CopyAssign);
  }

  for (const auto &Base : ClassDecl->vbases()) {
    CXXRecordDecl *BaseClassDecl
      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
    if (CXXMethodDecl *CopyAssign = LookupCopyingAssignment(BaseClassDecl,
                                                            ArgQuals, false, 0))
      ExceptSpec.CalledDecl(Base.getLocStart(), CopyAssign);
  }

  for (const auto *Field : ClassDecl->fields()) {
    QualType FieldType = Context.getBaseElementType(Field->getType());
    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
      if (CXXMethodDecl *CopyAssign =
          LookupCopyingAssignment(FieldClassDecl,
                                  ArgQuals | FieldType.getCVRQualifiers(),
                                  false, 0))
        ExceptSpec.CalledDecl(Field->getLocation(), CopyAssign);
    }
  }

  return ExceptSpec;
}

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

  // Build an exception specification pointing back at this member.
  FunctionProtoType::ExtProtoInfo EPI =
      getImplicitMethodEPI(*this, CopyAssignment);
  CopyAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));

  // 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.
  ++ASTContext::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,
                                            SourceLocation UseLoc) {
  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);
    S.Diag(UseLoc, diag::note_member_synthesized_at)
      << (isa<CXXConstructorDecl>(CopyOp) ? Sema::CXXCopyConstructor
                                          : Sema::CXXCopyAssignment)
      << RD;
  }
}

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

  CXXRecordDecl *ClassDecl = CopyAssignOperator->getParent();

  if (ClassDecl->isInvalidDecl() || CopyAssignOperator->isInvalidDecl()) {
    CopyAssignOperator->setInvalidDecl();
    return;
  }

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

  CopyAssignOperator->markUsed(Context);

  SynthesizedFunctionScope Scope(*this, CopyAssignOperator);
  DiagnosticErrorTrap Trap(Diags);

  // 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->getLocEnd().isValid()
                           ? CopyAssignOperator->getLocEnd()
                           : 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.getCVRQualifiedType(
                       BaseType, CopyAssignOperator->getTypeQualifiers()),
                   VK_LValue, BasePath);

    // Build the copy.
    StmtResult Copy = buildSingleCopyAssign(*this, Loc, BaseType,
                                            To, From,
                                            /*CopyingBaseSubobject=*/true,
                                            /*Copying=*/true);
    if (Copy.isInvalid()) {
      Diag(CurrentLocation, diag::note_member_synthesized_at) 
        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
      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);
      Diag(CurrentLocation, diag::note_member_synthesized_at) 
        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
      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);
      Diag(CurrentLocation, diag::note_member_synthesized_at) 
        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
      Invalid = true;      
      continue;
    }

    // Suppress assigning zero-width bitfields.
    if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
      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()) {
      Diag(CurrentLocation, diag::note_member_synthesized_at) 
        << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
      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 (Trap.hasErrorOccurred()) {
        Diag(CurrentLocation, diag::note_member_synthesized_at) 
          << CXXCopyAssignment << Context.getTagDeclType(ClassDecl);
        Invalid = true;
      }
    }
  }

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       CopyAssignOperator->getType()->castAs<FunctionProtoType>());

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

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(CopyAssignOperator);
  }
}

Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD) {
  CXXRecordDecl *ClassDecl = MD->getParent();

  ImplicitExceptionSpecification ExceptSpec(*this);
  if (ClassDecl->isInvalidDecl())
    return ExceptSpec;

  // C++0x [except.spec]p14:
  //   An implicitly declared special member function (Clause 12) shall have an 
  //   exception-specification. [...]

  // It is unspecified whether or not an implicit move assignment operator
  // attempts to deduplicate calls to assignment operators of virtual bases are
  // made. As such, this exception specification is effectively unspecified.
  // Based on a similar decision made for constness in C++0x, we're erring on
  // the side of assuming such calls to be made regardless of whether they
  // actually happen.
  // Note that a move constructor is not implicitly declared when there are
  // virtual bases, but it can still be user-declared and explicitly defaulted.
  for (const auto &Base : ClassDecl->bases()) {
    if (Base.isVirtual())
      continue;

    CXXRecordDecl *BaseClassDecl
      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
    if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
                                                           0, false, 0))
      ExceptSpec.CalledDecl(Base.getLocStart(), MoveAssign);
  }

  for (const auto &Base : ClassDecl->vbases()) {
    CXXRecordDecl *BaseClassDecl
      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
    if (CXXMethodDecl *MoveAssign = LookupMovingAssignment(BaseClassDecl,
                                                           0, false, 0))
      ExceptSpec.CalledDecl(Base.getLocStart(), MoveAssign);
  }

  for (const auto *Field : ClassDecl->fields()) {
    QualType FieldType = Context.getBaseElementType(Field->getType());
    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
      if (CXXMethodDecl *MoveAssign =
              LookupMovingAssignment(FieldClassDecl,
                                     FieldType.getCVRQualifiers(),
                                     false, 0))
        ExceptSpec.CalledDecl(Field->getLocation(), MoveAssign);
    }
  }

  return ExceptSpec;
}

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);
  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.
  ++ASTContext::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->getLocStart(), diag::note_vbase_moved_here)
            << (Base->getCanonicalDecl() ==
                Existing->getType()->getAsCXXRecordDecl()->getCanonicalDecl())
            << Base << Existing->getType() << Existing->getSourceRange();
          S.Diag(BI.getLocStart(), 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");

  CXXRecordDecl *ClassDecl = MoveAssignOperator->getParent();

  if (ClassDecl->isInvalidDecl() || MoveAssignOperator->isInvalidDecl()) {
    MoveAssignOperator->setInvalidDecl();
    return;
  }
  
  MoveAssignOperator->markUsed(Context);

  SynthesizedFunctionScope Scope(*this, MoveAssignOperator);
  DiagnosticErrorTrap Trap(Diags);

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

  // 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();
  assert(!OtherRefType.getQualifiers() &&
         "Bad argument type of defaulted move assignment");

  // Our location for everything implicitly-generated.
  SourceLocation Loc = MoveAssignOperator->getLocEnd().isValid()
                           ? MoveAssignOperator->getLocEnd()
                           : 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.getCVRQualifiedType(
                       BaseType, MoveAssignOperator->getTypeQualifiers()),
                   VK_LValue, BasePath);

    // Build the move.
    StmtResult Move = buildSingleCopyAssign(*this, Loc, BaseType,
                                            To, From,
                                            /*CopyingBaseSubobject=*/true,
                                            /*Copying=*/false);
    if (Move.isInvalid()) {
      Diag(CurrentLocation, diag::note_member_synthesized_at) 
        << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
      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);
      Diag(CurrentLocation, diag::note_member_synthesized_at) 
        << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
      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);
      Diag(CurrentLocation, diag::note_member_synthesized_at) 
        << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
      Invalid = true;      
      continue;
    }

    // Suppress assigning zero-width bitfields.
    if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
      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()) {
      Diag(CurrentLocation, diag::note_member_synthesized_at) 
        << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
      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 (Trap.hasErrorOccurred()) {
        Diag(CurrentLocation, diag::note_member_synthesized_at) 
          << CXXMoveAssignment << Context.getTagDeclType(ClassDecl);
        Invalid = true;
      }
    }
  }

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       MoveAssignOperator->getType()->castAs<FunctionProtoType>());

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

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(MoveAssignOperator);
  }
}

Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD) {
  CXXRecordDecl *ClassDecl = MD->getParent();

  ImplicitExceptionSpecification ExceptSpec(*this);
  if (ClassDecl->isInvalidDecl())
    return ExceptSpec;

  const FunctionProtoType *T = MD->getType()->castAs<FunctionProtoType>();
  assert(T->getNumParams() >= 1 && "not a copy ctor");
  unsigned Quals = T->getParamType(0).getNonReferenceType().getCVRQualifiers();

  // C++ [except.spec]p14:
  //   An implicitly declared special member function (Clause 12) shall have an 
  //   exception-specification. [...]
  for (const auto &Base : ClassDecl->bases()) {
    // Virtual bases are handled below.
    if (Base.isVirtual())
      continue;
    
    CXXRecordDecl *BaseClassDecl
      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
    if (CXXConstructorDecl *CopyConstructor =
          LookupCopyingConstructor(BaseClassDecl, Quals))
      ExceptSpec.CalledDecl(Base.getLocStart(), CopyConstructor);
  }
  for (const auto &Base : ClassDecl->vbases()) {
    CXXRecordDecl *BaseClassDecl
      = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
    if (CXXConstructorDecl *CopyConstructor =
          LookupCopyingConstructor(BaseClassDecl, Quals))
      ExceptSpec.CalledDecl(Base.getLocStart(), CopyConstructor);
  }
  for (const auto *Field : ClassDecl->fields()) {
    QualType FieldType = Context.getBaseElementType(Field->getType());
    if (CXXRecordDecl *FieldClassDecl = FieldType->getAsCXXRecordDecl()) {
      if (CXXConstructorDecl *CopyConstructor =
              LookupCopyingConstructor(FieldClassDecl,
                                       Quals | FieldType.getCVRQualifiers()))
      ExceptSpec.CalledDecl(Field->getLocation(), CopyConstructor);
    }
  }

  return ExceptSpec;
}

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();
  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,
      /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
      Constexpr);
  CopyConstructor->setAccess(AS_public);
  CopyConstructor->setDefaulted();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXCopyConstructor,
                                            CopyConstructor,
                                            /* ConstRHS */ Const,
                                            /* Diagnose */ false);
  }

  // Build an exception specification pointing back at this member.
  FunctionProtoType::ExtProtoInfo EPI =
      getImplicitMethodEPI(*this, CopyConstructor);
  CopyConstructor->setType(
      Context.getFunctionType(Context.VoidTy, ArgType, EPI));

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

  // Note that we have declared this constructor.
  ++ASTContext::NumImplicitCopyConstructorsDeclared;

  Scope *S = getScopeForContext(ClassDecl);
  CheckImplicitSpecialMemberDeclaration(S, CopyConstructor);

  if (ShouldDeleteSpecialMember(CopyConstructor, CXXCopyConstructor))
    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");

  CXXRecordDecl *ClassDecl = CopyConstructor->getParent();
  assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");

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

  SynthesizedFunctionScope Scope(*this, CopyConstructor);
  DiagnosticErrorTrap Trap(Diags);

  if (SetCtorInitializers(CopyConstructor, /*AnyErrors=*/false) ||
      Trap.hasErrorOccurred()) {
    Diag(CurrentLocation, diag::note_member_synthesized_at) 
      << CXXCopyConstructor << Context.getTagDeclType(ClassDecl);
    CopyConstructor->setInvalidDecl();
  }  else {
    SourceLocation Loc = CopyConstructor->getLocEnd().isValid()
                             ? CopyConstructor->getLocEnd()
                             : CopyConstructor->getLocation();
    Sema::CompoundScopeRAII CompoundScope(*this);
    CopyConstructor->setBody(
        ActOnCompoundStmt(Loc, Loc, None, /*isStmtExpr=*/false).getAs<Stmt>());
  }

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       CopyConstructor->getType()->castAs<FunctionProtoType>());

  CopyConstructor->markUsed(Context);
  MarkVTableUsed(CurrentLocation, ClassDecl);

  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(CopyConstructor);
  }
}

Sema::ImplicitExceptionSpecification
Sema::ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD) {
  CXXRecordDecl *ClassDecl = MD->getParent();

  // C++ [except.spec]p14:
  //   An implicitly declared special member function (Clause 12) shall have an 
  //   exception-specification. [...]
  ImplicitExceptionSpecification ExceptSpec(*this);
  if (ClassDecl->isInvalidDecl())
    return ExceptSpec;

  // Direct base-class constructors.
  for (const auto &B : ClassDecl->bases()) {
    if (B.isVirtual()) // Handled below.
      continue;
    
    if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
      CXXConstructorDecl *Constructor =
          LookupMovingConstructor(BaseClassDecl, 0);
      // If this is a deleted function, add it anyway. This might be conformant
      // with the standard. This might not. I'm not sure. It might not matter.
      if (Constructor)
        ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
    }
  }

  // Virtual base-class constructors.
  for (const auto &B : ClassDecl->vbases()) {
    if (const RecordType *BaseType = B.getType()->getAs<RecordType>()) {
      CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(BaseType->getDecl());
      CXXConstructorDecl *Constructor =
          LookupMovingConstructor(BaseClassDecl, 0);
      // If this is a deleted function, add it anyway. This might be conformant
      // with the standard. This might not. I'm not sure. It might not matter.
      if (Constructor)
        ExceptSpec.CalledDecl(B.getLocStart(), Constructor);
    }
  }

  // Field constructors.
  for (const auto *F : ClassDecl->fields()) {
    QualType FieldType = Context.getBaseElementType(F->getType());
    if (CXXRecordDecl *FieldRecDecl = FieldType->getAsCXXRecordDecl()) {
      CXXConstructorDecl *Constructor =
          LookupMovingConstructor(FieldRecDecl, FieldType.getCVRQualifiers());
      // If this is a deleted function, add it anyway. This might be conformant
      // with the standard. This might not. I'm not sure. It might not matter.
      // In particular, the problem is that this function never gets called. It
      // might just be ill-formed because this function attempts to refer to
      // a deleted function here.
      if (Constructor)
        ExceptSpec.CalledDecl(F->getLocation(), Constructor);
    }
  }

  return ExceptSpec;
}

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 = Context.getRValueReferenceType(ClassType);

  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,
      /*isExplicit=*/false, /*isInline=*/true, /*isImplicitlyDeclared=*/true,
      Constexpr);
  MoveConstructor->setAccess(AS_public);
  MoveConstructor->setDefaulted();

  if (getLangOpts().CUDA) {
    inferCUDATargetForImplicitSpecialMember(ClassDecl, CXXMoveConstructor,
                                            MoveConstructor,
                                            /* ConstRHS */ false,
                                            /* Diagnose */ false);
  }

  // Build an exception specification pointing back at this member.
  FunctionProtoType::ExtProtoInfo EPI =
      getImplicitMethodEPI(*this, MoveConstructor);
  MoveConstructor->setType(
      Context.getFunctionType(Context.VoidTy, ArgType, EPI));

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

  // Note that we have declared this constructor.
  ++ASTContext::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");

  CXXRecordDecl *ClassDecl = MoveConstructor->getParent();
  assert(ClassDecl && "DefineImplicitMoveConstructor - invalid constructor");

  SynthesizedFunctionScope Scope(*this, MoveConstructor);
  DiagnosticErrorTrap Trap(Diags);

  if (SetCtorInitializers(MoveConstructor, /*AnyErrors=*/false) ||
      Trap.hasErrorOccurred()) {
    Diag(CurrentLocation, diag::note_member_synthesized_at) 
      << CXXMoveConstructor << Context.getTagDeclType(ClassDecl);
    MoveConstructor->setInvalidDecl();
  }  else {
    SourceLocation Loc = MoveConstructor->getLocEnd().isValid()
                             ? MoveConstructor->getLocEnd()
                             : MoveConstructor->getLocation();
    Sema::CompoundScopeRAII CompoundScope(*this);
    MoveConstructor->setBody(ActOnCompoundStmt(
        Loc, Loc, None, /*isStmtExpr=*/ false).getAs<Stmt>());
  }

  // The exception specification is needed because we are defining the
  // function.
  ResolveExceptionSpec(CurrentLocation,
                       MoveConstructor->getType()->castAs<FunctionProtoType>());

  MoveConstructor->markUsed(Context);
  MarkVTableUsed(CurrentLocation, ClassDecl);

  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) {
  CXXRecordDecl *Lambda = Conv->getParent();
  CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
  // If we are defining a specialization of a conversion to function-ptr
  // cache the deduced template arguments for this specialization
  // so that we can use them to retrieve the corresponding call-operator
  // and static-invoker. 
  const TemplateArgumentList *DeducedTemplateArgs = nullptr;

  // Retrieve the corresponding call-operator specialization.
  if (Lambda->isGenericLambda()) {
    assert(Conv->isFunctionTemplateSpecialization());
    FunctionTemplateDecl *CallOpTemplate = 
        CallOp->getDescribedFunctionTemplate();
    DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
    void *InsertPos = nullptr;
    FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
                                                DeducedTemplateArgs->asArray(),
                                                InsertPos);
    assert(CallOpSpec && 
          "Conversion operator must have a corresponding call operator");
    CallOp = cast<CXXMethodDecl>(CallOpSpec);
  }
  // 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);

  SynthesizedFunctionScope Scope(*this, Conv);
  DiagnosticErrorTrap Trap(Diags);
   
  // Retrieve the static invoker...
  CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
  // ... and get the corresponding specialization for a generic lambda.
  if (Lambda->isGenericLambda()) {
    assert(DeducedTemplateArgs && 
      "Must have deduced template arguments from Conversion Operator");
    FunctionTemplateDecl *InvokeTemplate = 
                          Invoker->getDescribedFunctionTemplate();
    void *InsertPos = nullptr;
    FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
                                                DeducedTemplateArgs->asArray(),
                                                InsertPos);
    assert(InvokeSpec && 
      "Must have a corresponding static invoker specialization");
    Invoker = cast<CXXMethodDecl>(InvokeSpec);
  }
  // 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(new (Context) CompoundStmt(Context, Return,
                                            Conv->getLocation(),
                                            Conv->getLocation()));

  Conv->markUsed(Context);
  Conv->setReferenced();
  
  // Fill in the __invoke function with a dummy implementation. IR generation
  // will fill in the actual details.
  Invoker->markUsed(Context);
  Invoker->setReferenced();
  Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
   
  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Conv);
    L->CompletedImplicitDefinition(Invoker);
   }
}



void Sema::DefineImplicitLambdaToBlockPointerConversion(
       SourceLocation CurrentLocation,
       CXXConversionDecl *Conv) 
{
  assert(!Conv->getParent()->isGenericLambda());

  Conv->markUsed(Context);
  
  SynthesizedFunctionScope Scope(*this, Conv);
  DiagnosticErrorTrap Trap(Diags);
  
  // 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(new (Context) CompoundStmt(Context, ReturnS,
                                           Conv->getLocation(), 
                                           Conv->getLocation()));
  
  // We're done; notify the mutation listener, if any.
  if (ASTMutationListener *L = getASTMutationListener()) {
    L->CompletedImplicitDefinition(Conv);
  }
}

/// \brief 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;
    
    // fall through
  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);

  // 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 (InstantiateInClassInitializer(Loc, Field, Pattern,
                                      getTemplateInstantiationArgs(Field)))
      return ExprError();
    return CXXDefaultInitExpr::Create(Context, Loc, Field);
  }

  // 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();
  if (OutermostClass == ParentRD) {
    Diag(Field->getLocEnd(), diag::err_in_class_initializer_not_yet_parsed)
        << ParentRD << Field;
  } else {
    Diag(Field->getLocEnd(),
         diag::err_in_class_initializer_not_yet_parsed_outer_class)
        << ParentRD << OutermostClass << Field;
  }

  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;

  CXXDestructorDecl *Destructor = LookupDestructor(ClassDecl);
  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);
}

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

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

  // C++ [basic.stc.dynamic.deallocation]p2:
  //   Each deallocation function shall return void and its first parameter 
  //   shall be void*.
  if (CheckOperatorNewDeleteTypes(SemaRef, FnDecl, SemaRef.Context.VoidTy, 
                                  SemaRef.Context.VoidPtrTy,
                                 diag::err_operator_delete_dependent_param_type,
                                 diag::err_operator_delete_param_type))
    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.ActiveTemplateInstantiations.empty())
          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.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 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.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] != '_') {
    // 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)
      << NumericLiteralParser::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,
                                  AttributeList *AttrList,
                                  SourceLocation SemiLoc) {
  Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc);
  // Attribute declarations appertain to empty declaration so we handle
  // them here.
  if (AttrList)
    ProcessDeclAttributeList(S, ED, AttrList);

  CurContext->addDecl(ED);
  return ED;
}

/// \brief 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().ObjC1) {
    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, 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,
                                             ForRedeclaration)) {
    // 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.getLocStart(),
                                              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;

    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());
      Diag(StaticAssertLoc, diag::err_static_assert_failed)
        << !AssertMessage << Msg.str() << AssertExpr->getSourceRange();
      Failed = true;
    }
  }

  Decl *Decl = StaticAssertDecl::Create(Context, CurContext, StaticAssertLoc,
                                        AssertExpr, AssertMessage, RParenLoc,
                                        Failed);

  CurContext->addDecl(Decl);
  return Decl;
}

/// \brief 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 (!ActiveTemplateInstantiations.empty()) {
    // Do not complain about the form of friend template types during
    // template instantiation; we will already have complained when the
    // template was declared.
  } 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().getLocStart(), 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,
                                    AttributeList *Attr,
                                    MultiTemplateParamsArg TempParamLists) {
  TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);

  bool isExplicitSpecialization = false;
  bool Invalid = false;

  if (TemplateParameterList *TemplateParams =
          MatchTemplateParametersToScopeSpecifier(
              TagLoc, NameLoc, SS, nullptr, TempParamLists, /*friend*/ true,
              isExplicitSpecialization, 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;
      isExplicitSpecialization = 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);
    }

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

  assert(DS.isFriendSpecified());
  assert(DS.getStorageClassSpec() == DeclSpec::SCS_unspecified);

  // 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, Declarator::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);
  DeclarationName Name = NameInfo.getName();
  assert(Name);

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

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

    // Ignore things found implicitly in the wrong scope.
    // TODO: better diagnostics for this case.  Suggesting the right
    // qualified scope would be nice...
    LookupResult::Filter F = Previous.makeFilter();
    while (F.hasNext()) {
      NamedDecl *D = F.next();
      if (!DC->InEnclosingNamespaceSetOf(
              D->getDeclContext()->getRedeclContext()))
        F.erase();
    }
    F.done();

    if (Previous.empty()) {
      D.setInvalidType();
      Diag(Loc, diag::err_qualified_friend_not_found)
          << Name << TInfo->getType();
      return nullptr;
    }

    // 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.
      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 UnqualifiedId::IK_ConstructorTemplateId:
    case UnqualifiedId::IK_ConstructorName:
      DiagArg = 0;
      break;
    case UnqualifiedId::IK_DestructorName:
      DiagArg = 1;
      break;
    case UnqualifiedId::IK_ConversionFunctionId:
      DiagArg = 2;
      break;
    case UnqualifiedId::IK_Identifier:
    case UnqualifiedId::IK_ImplicitSelfParam:
    case UnqualifiedId::IK_LiteralOperatorId:
    case UnqualifiedId::IK_OperatorFunctionId:
    case UnqualifiedId::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;
  }

  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 (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),
                                        E = MD->end_overridden_methods();
         I != E; ++I) {
      if (!(*MD->begin_overridden_methods())->isDeleted()) {
        if (!IssuedDiagnostic) {
          Diag(DelLoc, diag::err_deleted_override) << MD->getDeclName();
          IssuedDiagnostic = true;
        }
        Diag((*I)->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();

    // 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->getLocStart(),
           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 FunctionType *NewFT = New->getType()->getAs<FunctionType>();
  const FunctionType *OldFT = Old->getType()->getAs<FunctionType>();

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

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

/// \brief Determine whether the given declaration is a static data member.
static bool isStaticDataMember(const Decl *D) {
  if (const VarDecl *Var = dyn_cast_or_null<VarDecl>(D))
    return Var->isStaticDataMember();

  return false;
}

/// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse
/// an initializer for the out-of-line declaration 'Dcl'.  The scope
/// is a fresh scope pushed for just this purpose.
///
/// 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.
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 (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 (isStaticDataMember(D))
    PushExpressionEvaluationContext(PotentiallyEvaluated, D);
}

/// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an
/// initializer for the out-of-line 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 (isStaticDataMember(D))
    PopExpressionEvaluationContext();

  if (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;

  // Try to insert this class into the map.
  LoadExternalVTableUses();
  Class = cast<CXXRecordDecl>(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;

    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
        = Class->getTemplateSpecializationKind()
                                      == 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 = cast<CXXRecordDecl>(Class->getCanonicalDecl());
    if (VTablesUsed[Canonical])
      Consumer.HandleVTable(Class);

    // Optionally warn if we're emitting a weak vtable.
    if (Class->isExternallyVisible() &&
        Class->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
      const FunctionDecl *KeyFunctionDef = nullptr;
      if (!KeyFunction || 
          (KeyFunction->hasBody(KeyFunctionDef) && 
           KeyFunctionDef->isInlined()))
        Diag(Class->getLocation(), Class->getTemplateSpecializationKind() ==
             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) {
  // 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())
        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::SmallSet<CXXConstructorDecl*, 4> &Valid,
                           llvm::SmallSet<CXXConstructorDecl*, 4> &Invalid,
                           llvm::SmallSet<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::SmallSet<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 (llvm::SmallSet<CXXConstructorDecl *, 4>::iterator CI = Invalid.begin(),
                                                         CE = Invalid.end();
       CI != CE; ++CI)
    (*CI)->setInvalidDecl();
}

namespace {
  /// \brief 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_DynamicNone:
  case EST_MSAny:
  case EST_None:
    break;
    
  case EST_ComputedNoexcept:
    if (!Finder.TraverseStmt(Proto->getNoexceptExpr()))
      return true;
    
  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 (EST == EST_ComputedNoexcept) {
    // If an error occurred, there's no expression here.
    if (NoexceptExpr) {
      assert((NoexceptExpr->isTypeDependent() ||
              NoexceptExpr->getType()->getCanonicalTypeUnqualified() ==
              Context.BoolTy) &&
             "Parser should have made sure that the expression is boolean");
      if (IsTopLevel && NoexceptExpr &&
          DiagnoseUnexpandedParameterPack(NoexceptExpr)) {
        ESI.Type = EST_BasicNoexcept;
        return;
      }

      if (!NoexceptExpr->isValueDependent())
        NoexceptExpr = VerifyIntegerConstantExpression(NoexceptExpr, nullptr,
                         diag::err_noexcept_needs_constant_expression,
                         /*AllowFold*/ false).get();
      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 (CXXMethodDecl::method_iterator O = Method->begin_overridden_methods(),
                                     OEnd = Method->end_overridden_methods();
         O != OEnd; ++O)
      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,
                                       AttributeList *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().CPlusPlus1z;
  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, ForRedeclaration);
  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.getLocStart();
  const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData();
  MSPropertyDecl *NewPD = MSPropertyDecl::Create(
      Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId);
  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;
}
