diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 654 | 
1 files changed, 354 insertions, 300 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 02a05d518251..8afe7aca9750 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -57,26 +57,30 @@ bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,    return false;  } -// FIXME: Is this still too simple? +// Include attribute instantiation code. +#include "clang/Sema/AttrTemplateInstantiate.inc" +  void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, -                            const Decl *Tmpl, Decl *New) { +                            const Decl *Tmpl, Decl *New, +                            LateInstantiatedAttrVec *LateAttrs, +                            LocalInstantiationScope *OuterMostScope) {    for (AttrVec::const_iterator i = Tmpl->attr_begin(), e = Tmpl->attr_end();         i != e; ++i) {      const Attr *TmplAttr = *i; +      // FIXME: This should be generalized to more than just the AlignedAttr.      if (const AlignedAttr *Aligned = dyn_cast<AlignedAttr>(TmplAttr)) {        if (Aligned->isAlignmentDependent()) { -        // The alignment expression is not potentially evaluated. -        EnterExpressionEvaluationContext Unevaluated(*this, -                                                     Sema::Unevaluated); -          if (Aligned->isAlignmentExpr()) { +          // The alignment expression is a constant expression. +          EnterExpressionEvaluationContext Unevaluated(*this, +                                                       Sema::ConstantEvaluated); +            ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(),                                          TemplateArgs);            if (!Result.isInvalid())              AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>()); -        } -        else { +        } else {            TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(),                                               TemplateArgs,                                               Aligned->getLocation(), @@ -88,9 +92,18 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,        }      } -    // FIXME: Is cloning correct for all attributes? -    Attr *NewAttr = TmplAttr->clone(Context); -    New->addAttr(NewAttr); +    if (TmplAttr->isLateParsed() && LateAttrs) { +      // Late parsed attributes must be instantiated and attached after the +      // enclosing class has been instantiated.  See Sema::InstantiateClass. +      LocalInstantiationScope *Saved = 0; +      if (CurrentInstantiationScope) +        Saved = CurrentInstantiationScope->cloneScopes(OuterMostScope); +      LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New)); +    } else { +      Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, +                                                         *this, TemplateArgs); +      New->addAttr(NewAttr); +    }    }  } @@ -164,13 +177,18 @@ Decl *TemplateDeclInstantiator::InstantiateTypedefNameDecl(TypedefNameDecl *D,      }    } -  if (TypedefNameDecl *Prev = D->getPreviousDeclaration()) { +  if (TypedefNameDecl *Prev = D->getPreviousDecl()) {      NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev,                                                         TemplateArgs);      if (!InstPrev)        return 0; -    Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(InstPrev)); +    TypedefNameDecl *InstPrevTypedef = cast<TypedefNameDecl>(InstPrev); + +    // If the typedef types are not identical, reject them. +    SemaRef.isIncompatibleTypedef(InstPrevTypedef, Typedef); + +    Typedef->setPreviousDeclaration(InstPrevTypedef);    }    SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); @@ -206,7 +224,7 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {    TypeAliasDecl *Pattern = D->getTemplatedDecl();    TypeAliasTemplateDecl *PrevAliasTemplate = 0; -  if (Pattern->getPreviousDeclaration()) { +  if (Pattern->getPreviousDecl()) {      DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());      if (Found.first != Found.second) {        PrevAliasTemplate = dyn_cast<TypeAliasTemplateDecl>(*Found.first); @@ -234,66 +252,6 @@ TemplateDeclInstantiator::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) {    return Inst;  } -/// \brief Instantiate an initializer, breaking it into separate -/// initialization arguments. -/// -/// \param Init The initializer to instantiate. -/// -/// \param TemplateArgs Template arguments to be substituted into the -/// initializer. -/// -/// \param NewArgs Will be filled in with the instantiation arguments. -/// -/// \returns true if an error occurred, false otherwise -bool Sema::InstantiateInitializer(Expr *Init, -                            const MultiLevelTemplateArgumentList &TemplateArgs, -                                  SourceLocation &LParenLoc, -                                  ASTOwningVector<Expr*> &NewArgs, -                                  SourceLocation &RParenLoc) { -  NewArgs.clear(); -  LParenLoc = SourceLocation(); -  RParenLoc = SourceLocation(); - -  if (!Init) -    return false; - -  if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) -    Init = ExprTemp->getSubExpr(); - -  while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) -    Init = Binder->getSubExpr(); - -  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) -    Init = ICE->getSubExprAsWritten(); - -  if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { -    LParenLoc = ParenList->getLParenLoc(); -    RParenLoc = ParenList->getRParenLoc(); -    return SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(), -                      true, TemplateArgs, NewArgs); -  } - -  if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { -    if (!isa<CXXTemporaryObjectExpr>(Construct)) { -      if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, -                     TemplateArgs, NewArgs)) -        return true; - -      // FIXME: Fake locations! -      LParenLoc = PP.getLocForEndOfToken(Init->getLocStart()); -      RParenLoc = LParenLoc; -      return false; -    } -  } - -  ExprResult Result = SubstExpr(Init, TemplateArgs); -  if (Result.isInvalid()) -    return true; - -  NewArgs.push_back(Result.takeAs<Expr>()); -  return false; -} -  Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {    // If this is the variable for an anonymous struct or union,    // instantiate the anonymous struct/union type first. @@ -324,8 +282,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {                                   D->getStorageClass(),                                   D->getStorageClassAsWritten());    Var->setThreadSpecified(D->isThreadSpecified()); -  Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); +  Var->setInitStyle(D->getInitStyle());    Var->setCXXForRangeDecl(D->isCXXForRangeDecl()); +  Var->setConstexpr(D->isConstexpr());    // Substitute the nested name specifier, if any.    if (SubstQualifier(D, Var)) @@ -351,18 +310,23 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {                          Sema::LookupOrdinaryName, Sema::ForRedeclaration);    if (D->isStaticDataMember())      SemaRef.LookupQualifiedName(Previous, Owner, false); +   +  // In ARC, infer 'retaining' for variables of retainable type. +  if (SemaRef.getLangOpts().ObjCAutoRefCount &&  +      SemaRef.inferObjCARCLifetime(Var)) +    Var->setInvalidDecl(); +    SemaRef.CheckVariableDeclaration(Var, Previous);    if (D->isOutOfLine()) { -    if (!D->isStaticDataMember()) -      D->getLexicalDeclContext()->addDecl(Var); +    D->getLexicalDeclContext()->addDecl(Var);      Owner->makeDeclVisibleInContext(Var);    } else {      Owner->addDecl(Var);      if (Owner->isFunctionOrMethod())        SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Var);    } -  SemaRef.InstantiateAttrs(TemplateArgs, D, Var); +  SemaRef.InstantiateAttrs(TemplateArgs, D, Var, LateAttrs, StartingScope);    // Link instantiations of static data members back to the template from    // which they were instantiated. @@ -374,31 +338,21 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {      // We already have an initializer in the class.    } else if (D->getInit()) {      if (Var->isStaticDataMember() && !D->isOutOfLine()) -      SemaRef.PushExpressionEvaluationContext(Sema::Unevaluated); +      SemaRef.PushExpressionEvaluationContext(Sema::ConstantEvaluated);      else        SemaRef.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);      // Instantiate the initializer. -    SourceLocation LParenLoc, RParenLoc; -    ASTOwningVector<Expr*> InitArgs(SemaRef); -    if (!SemaRef.InstantiateInitializer(D->getInit(), TemplateArgs, LParenLoc, -                                        InitArgs, RParenLoc)) { +    ExprResult Init = SemaRef.SubstInitializer(D->getInit(), TemplateArgs, +                                        D->getInitStyle() == VarDecl::CallInit); +    if (!Init.isInvalid()) {        bool TypeMayContainAuto = true; -      // Attach the initializer to the declaration, if we have one. -      if (InitArgs.size() == 0) +      if (Init.get()) { +        bool DirectInit = D->isDirectInit(); +        SemaRef.AddInitializerToDecl(Var, Init.take(), DirectInit, +                                     TypeMayContainAuto); +      } else          SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto); -      else if (D->hasCXXDirectInitializer()) { -        // Add the direct initializer to the declaration. -        SemaRef.AddCXXDirectInitializerToDecl(Var, -                                              LParenLoc, -                                              move_arg(InitArgs), -                                              RParenLoc, -                                              TypeMayContainAuto); -      } else { -        assert(InitArgs.size() == 1); -        Expr *Init = InitArgs.take()[0]; -        SemaRef.AddInitializerToDecl(Var, Init, false, TypeMayContainAuto); -      }      } else {        // FIXME: Not too happy about invalidating the declaration        // because of a bogus initializer. @@ -456,8 +410,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {    if (Invalid)      BitWidth = 0;    else if (BitWidth) { -    // The bit-width expression is not potentially evaluated. -    EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); +    // The bit-width expression is a constant expression. +    EnterExpressionEvaluationContext Unevaluated(SemaRef, +                                                 Sema::ConstantEvaluated);      ExprResult InstantiatedBitWidth        = SemaRef.SubstExpr(BitWidth, TemplateArgs); @@ -483,7 +438,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {      return 0;    } -  SemaRef.InstantiateAttrs(TemplateArgs, D, Field); +  SemaRef.InstantiateAttrs(TemplateArgs, D, Field, LateAttrs, StartingScope);    if (Invalid)      Field->setInvalidDecl(); @@ -552,7 +507,8 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {      if (!InstTy)        return 0; -    FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getFriendLoc(), InstTy); +    FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocation(), +                                                 D->getFriendLoc(), InstTy);      if (!FD)        return 0; @@ -584,8 +540,9 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {  Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {    Expr *AssertExpr = D->getAssertExpr(); -  // The expression in a static assertion is not potentially evaluated. -  EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); +  // The expression in a static assertion is a constant expression. +  EnterExpressionEvaluationContext Unevaluated(SemaRef, +                                               Sema::ConstantEvaluated);    ExprResult InstantiatedAssertExpr      = SemaRef.SubstExpr(AssertExpr, TemplateArgs); @@ -601,25 +558,32 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {  }  Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { +  EnumDecl *PrevDecl = 0; +  if (D->getPreviousDecl()) { +    NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), +                                                   D->getPreviousDecl(), +                                                   TemplateArgs); +    if (!Prev) return 0; +    PrevDecl = cast<EnumDecl>(Prev); +  } +    EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocStart(),                                      D->getLocation(), D->getIdentifier(), -                                    /*PrevDecl=*/0, D->isScoped(), +                                    PrevDecl, D->isScoped(),                                      D->isScopedUsingClassTag(), D->isFixed());    if (D->isFixed()) { -    if (TypeSourceInfo* TI = D->getIntegerTypeSourceInfo()) { +    if (TypeSourceInfo *TI = D->getIntegerTypeSourceInfo()) {        // If we have type source information for the underlying type, it means it        // has been explicitly set by the user. Perform substitution on it before        // moving on.        SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); -      Enum->setIntegerTypeSourceInfo(SemaRef.SubstType(TI, -                                                       TemplateArgs, -                                                       UnderlyingLoc, -                                                       DeclarationName())); - -      if (!Enum->getIntegerTypeSourceInfo()) +      TypeSourceInfo *NewTI = SemaRef.SubstType(TI, TemplateArgs, UnderlyingLoc, +                                                DeclarationName()); +      if (!NewTI || SemaRef.CheckEnumUnderlyingType(NewTI))          Enum->setIntegerType(SemaRef.Context.IntTy); -    } -    else { +      else +        Enum->setIntegerTypeSourceInfo(NewTI); +    } else {        assert(!D->getIntegerType()->isDependentType()               && "Dependent type without type source info");        Enum->setIntegerType(D->getIntegerType()); @@ -628,27 +592,62 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {    SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); -  Enum->setInstantiationOfMemberEnum(D); +  Enum->setInstantiationOfMemberEnum(D, TSK_ImplicitInstantiation);    Enum->setAccess(D->getAccess());    if (SubstQualifier(D, Enum)) return 0;    Owner->addDecl(Enum); -  Enum->startDefinition(); + +  EnumDecl *Def = D->getDefinition(); +  if (Def && Def != D) { +    // If this is an out-of-line definition of an enum member template, check +    // that the underlying types match in the instantiation of both +    // declarations. +    if (TypeSourceInfo *TI = Def->getIntegerTypeSourceInfo()) { +      SourceLocation UnderlyingLoc = TI->getTypeLoc().getBeginLoc(); +      QualType DefnUnderlying = +        SemaRef.SubstType(TI->getType(), TemplateArgs, +                          UnderlyingLoc, DeclarationName()); +      SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), +                                     DefnUnderlying, Enum); +    } +  }    if (D->getDeclContext()->isFunctionOrMethod())      SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, Enum); +  // C++11 [temp.inst]p1: The implicit instantiation of a class template +  // specialization causes the implicit instantiation of the declarations, but +  // not the definitions of scoped member enumerations. +  // FIXME: There appears to be no wording for what happens for an enum defined +  // within a block scope, but we treat that much like a member template. Only +  // instantiate the definition when visiting the definition in that case, since +  // we will visit all redeclarations. +  if (!Enum->isScoped() && Def && +      (!D->getDeclContext()->isFunctionOrMethod() || D->isCompleteDefinition())) +    InstantiateEnumDefinition(Enum, Def); + +  return Enum; +} + +void TemplateDeclInstantiator::InstantiateEnumDefinition( +    EnumDecl *Enum, EnumDecl *Pattern) { +  Enum->startDefinition(); + +  // Update the location to refer to the definition. +  Enum->setLocation(Pattern->getLocation()); +    SmallVector<Decl*, 4> Enumerators;    EnumConstantDecl *LastEnumConst = 0; -  for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(), -         ECEnd = D->enumerator_end(); +  for (EnumDecl::enumerator_iterator EC = Pattern->enumerator_begin(), +         ECEnd = Pattern->enumerator_end();         EC != ECEnd; ++EC) {      // The specified value for the enumerator.      ExprResult Value = SemaRef.Owned((Expr *)0);      if (Expr *UninstValue = EC->getInitExpr()) { -      // The enumerator's value expression is not potentially evaluated. +      // The enumerator's value expression is a constant expression.        EnterExpressionEvaluationContext Unevaluated(SemaRef, -                                                   Sema::Unevaluated); +                                                   Sema::ConstantEvaluated);        Value = SemaRef.SubstExpr(UninstValue, TemplateArgs);      } @@ -679,7 +678,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {        Enumerators.push_back(EnumConst);        LastEnumConst = EnumConst; -      if (D->getDeclContext()->isFunctionOrMethod()) { +      if (Pattern->getDeclContext()->isFunctionOrMethod() && +          !Enum->isScoped()) {          // If the enumeration is within a function or method, record the enum          // constant as a local.          SemaRef.CurrentInstantiationScope->InstantiatedLocal(*EC, EnumConst); @@ -687,14 +687,11 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {      }    } -  // FIXME: Fixup LBraceLoc and RBraceLoc -  // FIXME: Empty Scope and AttributeList (required to handle attribute packed). -  SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), SourceLocation(), -                        Enum, +  // FIXME: Fixup LBraceLoc +  SemaRef.ActOnEnumBody(Enum->getLocation(), SourceLocation(), +                        Enum->getRBraceLoc(), Enum,                          Enumerators.data(), Enumerators.size(),                          0, 0); - -  return Enum;  }  Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { @@ -728,7 +725,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {    CXXRecordDecl *PrevDecl = 0;    ClassTemplateDecl *PrevClassTemplate = 0; -  if (!isFriend && Pattern->getPreviousDeclaration()) { +  if (!isFriend && Pattern->getPreviousDecl()) {      DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName());      if (Found.first != Found.second) {        PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first); @@ -860,10 +857,17 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {    // Finish handling of friends.    if (isFriend) { -    DC->makeDeclVisibleInContext(Inst, /*Recoverable*/ false); +    DC->makeDeclVisibleInContext(Inst); +    Inst->setLexicalDeclContext(Owner); +    RecordInst->setLexicalDeclContext(Owner);      return Inst;    } +  if (D->isOutOfLine()) { +    Inst->setLexicalDeclContext(D->getLexicalDeclContext()); +    RecordInst->setLexicalDeclContext(D->getLexicalDeclContext()); +  } +    Owner->addDecl(Inst);    if (!PrevClassTemplate) { @@ -958,9 +962,9 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {    CXXRecordDecl *PrevDecl = 0;    if (D->isInjectedClassName())      PrevDecl = cast<CXXRecordDecl>(Owner); -  else if (D->getPreviousDeclaration()) { +  else if (D->getPreviousDecl()) {      NamedDecl *Prev = SemaRef.FindInstantiatedDecl(D->getLocation(), -                                                   D->getPreviousDeclaration(), +                                                   D->getPreviousDecl(),                                                     TemplateArgs);      if (!Prev) return 0;      PrevDecl = cast<CXXRecordDecl>(Prev); @@ -1010,11 +1014,11 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,    // Check whether there is already a function template specialization for    // this declaration.    FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); -  void *InsertPos = 0;    if (FunctionTemplate && !TemplateParams) {      std::pair<const TemplateArgument *, unsigned> Innermost        = TemplateArgs.getInnermost(); +    void *InsertPos = 0;      FunctionDecl *SpecFunc        = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,                                               InsertPos); @@ -1037,8 +1041,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,    LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);    SmallVector<ParmVarDecl *, 4> Params; -  TypeSourceInfo *TInfo = D->getTypeSourceInfo(); -  TInfo = SubstFunctionType(D, Params); +  TypeSourceInfo *TInfo = SubstFunctionType(D, Params);    if (!TInfo)      return 0;    QualType T = TInfo->getType(); @@ -1071,7 +1074,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,                             D->getLocation(), D->getDeclName(), T, TInfo,                             D->getStorageClass(), D->getStorageClassAsWritten(),                             D->isInlineSpecified(), D->hasWrittenPrototype(), -                           /*isConstexpr*/ false); +                           D->isConstexpr());    if (QualifierLoc)      Function->setQualifierInfo(QualifierLoc); @@ -1145,7 +1148,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,                              TemplateArgumentList::CreateCopy(SemaRef.Context,                                                               Innermost.first,                                                               Innermost.second), -                                                InsertPos); +                                                /*InsertPos=*/0);    } else if (isFriend) {      // Note, we need this connection even if the friend doesn't have a body.      // Its body may exist but not have been attached yet due to deferred @@ -1221,25 +1224,42 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,    if (isFriend) {      NamedDecl *PrevDecl;      if (TemplateParams) -      PrevDecl = FunctionTemplate->getPreviousDeclaration(); +      PrevDecl = FunctionTemplate->getPreviousDecl();      else -      PrevDecl = Function->getPreviousDeclaration(); +      PrevDecl = Function->getPreviousDecl();      PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0); -    DC->makeDeclVisibleInContext(PrincipalDecl, /*Recoverable=*/ false); +    DC->makeDeclVisibleInContext(PrincipalDecl);      bool queuedInstantiation = false; -    if (!SemaRef.getLangOptions().CPlusPlus0x && +    // C++98 [temp.friend]p5: When a function is defined in a friend function +    //   declaration in a class template, the function is defined at each +    //   instantiation of the class template. The function is defined even if it +    //   is never used. +    // C++11 [temp.friend]p4: When a function is defined in a friend function +    //   declaration in a class template, the function is instantiated when the +    //   function is odr-used. +    // +    // If -Wc++98-compat is enabled, we go through the motions of checking for a +    // redefinition, but don't instantiate the function. +    if ((!SemaRef.getLangOpts().CPlusPlus0x || +         SemaRef.Diags.getDiagnosticLevel( +             diag::warn_cxx98_compat_friend_redefinition, +             Function->getLocation()) +           != DiagnosticsEngine::Ignored) &&          D->isThisDeclarationADefinition()) {        // Check for a function body.        const FunctionDecl *Definition = 0;        if (Function->isDefined(Definition) &&            Definition->getTemplateSpecializationKind() == TSK_Undeclared) { -        SemaRef.Diag(Function->getLocation(), diag::err_redefinition) -          << Function->getDeclName(); +        SemaRef.Diag(Function->getLocation(), +                     SemaRef.getLangOpts().CPlusPlus0x ? +                       diag::warn_cxx98_compat_friend_redefinition : +                       diag::err_redefinition) << Function->getDeclName();          SemaRef.Diag(Definition->getLocation(), diag::note_previous_definition); -        Function->setInvalidDecl(); +        if (!SemaRef.getLangOpts().CPlusPlus0x) +          Function->setInvalidDecl();        }        // Check for redefinitions due to other instantiations of this or        // a similar friend function. @@ -1250,7 +1270,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,            continue;          switch (R->getFriendObjectKind()) {          case Decl::FOK_None: -          if (!queuedInstantiation && R->isUsed(false)) { +          if (!SemaRef.getLangOpts().CPlusPlus0x && +              !queuedInstantiation && R->isUsed(false)) {              if (MemberSpecializationInfo *MSInfo                  = Function->getMemberSpecializationInfo()) {                if (MSInfo->getPointOfInstantiation().isInvalid()) { @@ -1267,10 +1288,14 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,            if (const FunctionDecl *RPattern                = R->getTemplateInstantiationPattern())              if (RPattern->isDefined(RPattern)) { -              SemaRef.Diag(Function->getLocation(), diag::err_redefinition) +              SemaRef.Diag(Function->getLocation(), +                           SemaRef.getLangOpts().CPlusPlus0x ? +                             diag::warn_cxx98_compat_friend_redefinition : +                             diag::err_redefinition)                  << Function->getDeclName();                SemaRef.Diag(R->getLocation(), diag::note_previous_definition); -              Function->setInvalidDecl(); +              if (!SemaRef.getLangOpts().CPlusPlus0x) +                Function->setInvalidDecl();                break;              }          } @@ -1291,7 +1316,6 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,                                        TemplateParameterList *TemplateParams,                                        bool IsClassScopeSpecialization) {    FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); -  void *InsertPos = 0;    if (FunctionTemplate && !TemplateParams) {      // We are creating a function template specialization from a function      // template. Check whether there is already a function template @@ -1299,6 +1323,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,      std::pair<const TemplateArgument *, unsigned> Innermost        = TemplateArgs.getInnermost(); +    void *InsertPos = 0;      FunctionDecl *SpecFunc        = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second,                                               InsertPos); @@ -1334,8 +1359,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,    }    SmallVector<ParmVarDecl *, 4> Params; -  TypeSourceInfo *TInfo = D->getTypeSourceInfo(); -  TInfo = SubstFunctionType(D, Params); +  TypeSourceInfo *TInfo = SubstFunctionType(D, Params);    if (!TInfo)      return 0;    QualType T = TInfo->getType(); @@ -1395,7 +1419,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,                                          StartLoc, NameInfo, T, TInfo,                                          Constructor->isExplicit(),                                          Constructor->isInlineSpecified(), -                                        false, /*isConstexpr*/ false); +                                        false, Constructor->isConstexpr());    } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) {      Method = CXXDestructorDecl::Create(SemaRef.Context, Record,                                         StartLoc, NameInfo, T, TInfo, @@ -1406,7 +1430,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,                                         StartLoc, NameInfo, T, TInfo,                                         Conversion->isInlineSpecified(),                                         Conversion->isExplicit(), -                                       /*isConstexpr*/ false, +                                       Conversion->isConstexpr(),                                         Conversion->getLocEnd());    } else {      Method = CXXMethodDecl::Create(SemaRef.Context, Record, @@ -1414,7 +1438,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,                                     D->isStatic(),                                     D->getStorageClassAsWritten(),                                     D->isInlineSpecified(), -                                   /*isConstexpr*/ false, D->getLocEnd()); +                                   D->isConstexpr(), D->getLocEnd());    }    if (QualifierLoc) @@ -1452,7 +1476,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,                           TemplateArgumentList::CreateCopy(SemaRef.Context,                                                            Innermost.first,                                                            Innermost.second), -                                              InsertPos); +                                              /*InsertPos=*/0);    } else if (!isFriend) {      // Record that this is an instantiation of a member function.      Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation); @@ -1504,6 +1528,12 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,    SemaRef.CheckOverrideControl(Method); +  // If a function is defined as defaulted or deleted, mark it as such now. +  if (D->isDefaulted()) +    Method->setDefaulted(); +  if (D->isDeletedAsWritten()) +    Method->setDeletedAsWritten(); +    if (FunctionTemplate) {      // If there's a function template, let our caller handle it.    } else if (Method->isInvalidDecl() && !Previous.empty()) { @@ -1542,7 +1572,8 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) {  ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) {    return SemaRef.SubstParmVarDecl(D, TemplateArgs, /*indexAdjustment*/ 0, -                                  llvm::Optional<unsigned>()); +                                  llvm::Optional<unsigned>(), +                                  /*ExpectParameterPack=*/false);  }  Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( @@ -1825,6 +1856,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {    if (NewUD->isInvalidDecl())      return NewUD; +  if (NameInfo.getName().getNameKind() == DeclarationName::CXXConstructorName) { +    if (SemaRef.CheckInheritingConstructorUsingDecl(NewUD)) +      NewUD->setInvalidDecl(); +    return NewUD; +  } +    bool isFunctionScope = Owner->isFunctionOrMethod();    // Process the shadow decls. @@ -2094,7 +2131,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(    // Add this partial specialization to the set of class template partial    // specializations. -  ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos); +  ClassTemplate->AddPartialSpecialization(InstPartialSpec, /*InsertPos=*/0);    return InstPartialSpec;  } @@ -2124,6 +2161,8 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,             OldIdx != NumOldParams; ++OldIdx) {          ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx);          if (!OldParam->isParameterPack() || +            // FIXME: Is this right? OldParam could expand to an empty parameter +            // pack and the next parameter could be an unexpanded parameter pack              (NewIdx < NumNewParams &&               NewProtoLoc->getArg(NewIdx)->isParameterPack())) {            // Simple case: normal parameter, or a parameter pack that's @@ -2280,23 +2319,19 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,      }      Expr *NoexceptExpr = 0;      if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) { -      EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); +      EnterExpressionEvaluationContext Unevaluated(SemaRef, +                                                   Sema::ConstantEvaluated);        ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);        if (E.isUsable())          E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart()); -     +        if (E.isUsable()) { -        SourceLocation ErrLoc; -        llvm::APSInt NoexceptVal;          NoexceptExpr = E.take();          if (!NoexceptExpr->isTypeDependent() && -            !NoexceptExpr->isValueDependent() && -            !NoexceptExpr->isIntegerConstantExpr(NoexceptVal, SemaRef.Context, -                                                 &ErrLoc, /*evaluated=*/false)){ -          SemaRef.Diag(ErrLoc, diag::err_noexcept_needs_constant_expression) -            << NoexceptExpr->getSourceRange(); -          NoexceptExpr = 0; -        } +            !NoexceptExpr->isValueDependent()) +          NoexceptExpr = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr, +            0, SemaRef.PDiag(diag::err_noexcept_needs_constant_expression), +            /*AllowFold*/ false).take();        }      } @@ -2318,19 +2353,13 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,                                                   EPI));    } -  // C++0x [dcl.constexpr]p6: If the instantiated template specialization of -  // a constexpr function template satisfies the requirements for a constexpr -  // function, then it is a constexpr function. -  if (Tmpl->isConstexpr() && -      SemaRef.CheckConstexprFunctionDecl(New, Sema::CCK_Instantiation)) -    New->setConstexpr(true); -    const FunctionDecl* Definition = Tmpl;    // Get the definition. Leaves the variable unchanged if undefined.    Tmpl->isDefined(Definition); -  SemaRef.InstantiateAttrs(TemplateArgs, Definition, New); +  SemaRef.InstantiateAttrs(TemplateArgs, Definition, New, +                           LateAttrs, StartingScope);    return false;  } @@ -2450,6 +2479,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,    if (Inst)      return; +  // Copy the inner loc start from the pattern. +  Function->setInnerLocStart(PatternDecl->getInnerLocStart()); +    // If we're performing recursive template instantiation, create our own    // queue of pending implicit instantiations that we will instantiate later,    // while we're still within our own instantiation context. @@ -2474,6 +2506,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,    LocalInstantiationScope Scope(*this, MergeWithParentScope); +  // Enter the scope of this instantiation. We don't use +  // PushDeclContext because we don't have a scope. +  Sema::ContextRAII savedContext(*this, Function); + +  MultiLevelTemplateArgumentList TemplateArgs = +    getTemplateInstantiationArgs(Function, 0, false, PatternDecl); +    // Introduce the instantiated function parameters into the local    // instantiation scope, and set the parameter names to those used    // in the template. @@ -2483,7 +2522,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,      if (!PatternParam->isParameterPack()) {        // Simple case: not a parameter pack.        assert(FParamIdx < Function->getNumParams()); -      ParmVarDecl *FunctionParam = Function->getParamDecl(I); +      ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);        FunctionParam->setDeclName(PatternParam->getDeclName());        Scope.InstantiatedLocal(PatternParam, FunctionParam);        ++FParamIdx; @@ -2492,22 +2531,16 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,      // Expand the parameter pack.      Scope.MakeInstantiatedLocalArgPack(PatternParam); -    for (unsigned NumFParams = Function->getNumParams(); -         FParamIdx < NumFParams; -         ++FParamIdx) { +    unsigned NumArgumentsInExpansion +      = getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); +    for (unsigned Arg = 0; Arg < NumArgumentsInExpansion; ++Arg) {        ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);        FunctionParam->setDeclName(PatternParam->getDeclName());        Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); +      ++FParamIdx;      }    } -  // Enter the scope of this instantiation. We don't use -  // PushDeclContext because we don't have a scope. -  Sema::ContextRAII savedContext(*this, Function); - -  MultiLevelTemplateArgumentList TemplateArgs = -    getTemplateInstantiationArgs(Function, 0, false, PatternDecl); -    if (PatternDecl->isDefaulted()) {      ActOnFinishFunctionBody(Function, 0, /*IsInstantiation=*/true); @@ -2612,21 +2645,29 @@ void Sema::InstantiateStaticDataMemberDefinition(      return;    } +  TemplateSpecializationKind TSK = Var->getTemplateSpecializationKind(); +    // Never instantiate an explicit specialization. -  if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) +  if (TSK == TSK_ExplicitSpecialization)      return;    // C++0x [temp.explicit]p9:    //   Except for inline functions, other explicit instantiation declarations    //   have the effect of suppressing the implicit instantiation of the entity    //   to which they refer. -  if (Var->getTemplateSpecializationKind() -        == TSK_ExplicitInstantiationDeclaration) +  if (TSK == TSK_ExplicitInstantiationDeclaration)      return; +  Consumer.HandleCXXStaticMemberVarInstantiation(Var); +    // If we already have a definition, we're done. -  if (Var->getDefinition()) +  if (VarDecl *Def = Var->getDefinition()) { +    // We may be explicitly instantiating something we've already implicitly +    // instantiated. +    Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(), +                                       PointOfInstantiation);      return; +  }    InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);    if (Inst) @@ -2645,7 +2686,8 @@ void Sema::InstantiateStaticDataMemberDefinition(    // Enter the scope of this instantiation. We don't use    // PushDeclContext because we don't have a scope.    ContextRAII previousContext(*this, Var->getDeclContext()); - +  LocalInstantiationScope Local(*this); +      VarDecl *OldVar = Var;    Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),                                          getTemplateInstantiationArgs(Var))); @@ -2660,7 +2702,8 @@ void Sema::InstantiateStaticDataMemberDefinition(      DeclGroupRef DG(Var);      Consumer.HandleTopLevelDecl(DG);    } - +  Local.Exit(); +      if (Recursive) {      // Define any newly required vtables.      DefineUsedVTables(); @@ -2683,18 +2726,6 @@ void Sema::InstantiateStaticDataMemberDefinition(    }  } -static MultiInitializer CreateMultiInitializer(SmallVectorImpl<Expr*> &Args, -                                               const CXXCtorInitializer *Init) { -  // FIXME: This is a hack that will do slightly the wrong thing for an -  // initializer of the form foo({...}). -  // The right thing to do would be to modify InstantiateInitializer to create -  // the MultiInitializer. -  if (Args.size() == 1 && isa<InitListExpr>(Args[0])) -    return MultiInitializer(Args[0]); -  return MultiInitializer(Init->getLParenLoc(), Args.data(), -                          Args.size(), Init->getRParenLoc()); -} -  void  Sema::InstantiateMemInitializers(CXXConstructorDecl *New,                                   const CXXConstructorDecl *Tmpl, @@ -2714,14 +2745,11 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,      if (!Init->isWritten())        continue; -    SourceLocation LParenLoc, RParenLoc; -    ASTOwningVector<Expr*> NewArgs(*this); -      SourceLocation EllipsisLoc;      if (Init->isPackExpansion()) {        // This is a pack expansion. We should expand it now. -      TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc(); +      TypeLoc BaseTL = Init->getTypeSourceInfo()->getTypeLoc();        SmallVector<UnexpandedParameterPack, 2> Unexpanded;        collectUnexpandedParameterPacks(BaseTL, Unexpanded);        bool ShouldExpand = false; @@ -2744,14 +2772,15 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,          Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);          // Instantiate the initializer. -        if (InstantiateInitializer(Init->getInit(), TemplateArgs, -                                   LParenLoc, NewArgs, RParenLoc)) { +        ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, +                                               /*CXXDirectInit=*/true); +        if (TempInit.isInvalid()) {            AnyErrors = true;            break;          }          // Instantiate the base type. -        TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), +        TypeSourceInfo *BaseTInfo = SubstType(Init->getTypeSourceInfo(),                                                TemplateArgs,                                                Init->getSourceLocation(),                                                New->getDeclName()); @@ -2761,9 +2790,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,          }          // Build the initializer. -        MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init));          MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), -                                                     BaseTInfo, MultiInit, +                                                     BaseTInfo, TempInit.take(),                                                       New->getParent(),                                                       SourceLocation());          if (NewInit.isInvalid()) { @@ -2772,34 +2800,37 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,          }          NewInits.push_back(NewInit.get()); -        NewArgs.clear();        }        continue;      }      // Instantiate the initializer. -    if (InstantiateInitializer(Init->getInit(), TemplateArgs, -                               LParenLoc, NewArgs, RParenLoc)) { +    ExprResult TempInit = SubstInitializer(Init->getInit(), TemplateArgs, +                                           /*CXXDirectInit=*/true); +    if (TempInit.isInvalid()) {        AnyErrors = true;        continue;      }      MemInitResult NewInit; -    if (Init->isBaseInitializer()) { -      TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), -                                            TemplateArgs, -                                            Init->getSourceLocation(), -                                            New->getDeclName()); -      if (!BaseTInfo) { +    if (Init->isDelegatingInitializer() || Init->isBaseInitializer()) { +      TypeSourceInfo *TInfo = SubstType(Init->getTypeSourceInfo(), +                                        TemplateArgs, +                                        Init->getSourceLocation(), +                                        New->getDeclName()); +      if (!TInfo) {          AnyErrors = true;          New->setInvalidDecl();          continue;        } -      MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); -      NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, MultiInit, -                                     New->getParent(), EllipsisLoc); +      if (Init->isBaseInitializer()) +        NewInit = BuildBaseInitializer(TInfo->getType(), TInfo, TempInit.take(), +                                       New->getParent(), EllipsisLoc); +      else +        NewInit = BuildDelegatingInitializer(TInfo, TempInit.take(), +                                  cast<CXXRecordDecl>(CurContext->getParent()));      } else if (Init->isMemberInitializer()) {        FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl(                                                       Init->getMemberLocation(), @@ -2811,8 +2842,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,          continue;        } -      MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); -      NewInit = BuildMemberInitializer(Member, MultiInit, +      NewInit = BuildMemberInitializer(Member, TempInit.take(),                                         Init->getSourceLocation());      } else if (Init->isIndirectMemberInitializer()) {        IndirectFieldDecl *IndirectMember = @@ -2826,8 +2856,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,          continue;        } -      MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); -      NewInit = BuildMemberInitializer(IndirectMember, MultiInit, +      NewInit = BuildMemberInitializer(IndirectMember, TempInit.take(),                                         Init->getSourceLocation());      } @@ -2835,9 +2864,6 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,        AnyErrors = true;        New->setInvalidDecl();      } else { -      // FIXME: It would be nice if ASTOwningVector had a release function. -      NewArgs.take(); -        NewInits.push_back(NewInit.get());      }    } @@ -2850,6 +2876,45 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New,                         AnyErrors);  } +ExprResult Sema::SubstInitializer(Expr *Init, +                          const MultiLevelTemplateArgumentList &TemplateArgs, +                          bool CXXDirectInit) { +  // Initializers are instantiated like expressions, except that various outer +  // layers are stripped. +  if (!Init) +    return Owned(Init); + +  if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) +    Init = ExprTemp->getSubExpr(); + +  while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) +    Init = Binder->getSubExpr(); + +  if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Init)) +    Init = ICE->getSubExprAsWritten(); + +  // If this is a direct-initializer, we take apart CXXConstructExprs. +  // Everything else is passed through. +  CXXConstructExpr *Construct; +  if (!CXXDirectInit || !(Construct = dyn_cast<CXXConstructExpr>(Init)) || +      isa<CXXTemporaryObjectExpr>(Construct)) +    return SubstExpr(Init, TemplateArgs); + +  ASTOwningVector<Expr*> NewArgs(*this); +  if (SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, +                 TemplateArgs, NewArgs)) +    return ExprError(); + +  // Treat an empty initializer like none. +  if (NewArgs.empty()) +    return Owned((Expr*)0); + +  // Build a ParenListExpr to represent anything else. +  // FIXME: Fake locations! +  SourceLocation Loc = PP.getLocForEndOfToken(Init->getLocStart()); +  return ActOnParenListExpr(Loc, Loc, move_arg(NewArgs)); +} +  // TODO: this could be templated if the various decl types used the  // same method name.  static bool isInstantiationOf(ClassTemplateDecl *Pattern, @@ -3090,7 +3155,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,    DeclContext *ParentDC = D->getDeclContext();    if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||        isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || -      (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext())) { +      (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) || +      (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {      // D is a local of some kind. Look into the map of local      // declarations to their instantiations.      typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; @@ -3120,75 +3186,49 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,      if (!Record->isDependentContext())        return D; -    // If the RecordDecl is actually the injected-class-name or a -    // "templated" declaration for a class template, class template -    // partial specialization, or a member class of a class template, -    // substitute into the injected-class-name of the class template -    // or partial specialization to find the new DeclContext. -    QualType T; +    // Determine whether this record is the "templated" declaration describing +    // a class template or class template partial specialization.      ClassTemplateDecl *ClassTemplate = Record->getDescribedClassTemplate(); - -    if (ClassTemplate) { -      T = ClassTemplate->getInjectedClassNameSpecialization(); -    } else if (ClassTemplatePartialSpecializationDecl *PartialSpec -                 = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) { -      ClassTemplate = PartialSpec->getSpecializedTemplate(); - -      // If we call SubstType with an InjectedClassNameType here we -      // can end up in an infinite loop. -      T = Context.getTypeDeclType(Record); -      assert(isa<InjectedClassNameType>(T) && -             "type of partial specialization is not an InjectedClassNameType"); -      T = cast<InjectedClassNameType>(T)->getInjectedSpecializationType(); -    } - -    if (!T.isNull()) { -      // Substitute into the injected-class-name to get the type -      // corresponding to the instantiation we want, which may also be -      // the current instantiation (if we're in a template -      // definition). This substitution should never fail, since we -      // know we can instantiate the injected-class-name or we -      // wouldn't have gotten to the injected-class-name! - -      // FIXME: Can we use the CurrentInstantiationScope to avoid this -      // extra instantiation in the common case? -      T = SubstType(T, TemplateArgs, Loc, DeclarationName()); -      assert(!T.isNull() && "Instantiation of injected-class-name cannot fail."); - -      if (!T->isDependentType()) { -        assert(T->isRecordType() && "Instantiation must produce a record type"); -        return T->getAs<RecordType>()->getDecl(); +    if (ClassTemplate) +      ClassTemplate = ClassTemplate->getCanonicalDecl(); +    else if (ClassTemplatePartialSpecializationDecl *PartialSpec +               = dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) +      ClassTemplate = PartialSpec->getSpecializedTemplate()->getCanonicalDecl(); +     +    // Walk the current context to find either the record or an instantiation of +    // it. +    DeclContext *DC = CurContext; +    while (!DC->isFileContext()) { +      // If we're performing substitution while we're inside the template +      // definition, we'll find our own context. We're done. +      if (DC->Equals(Record)) +        return Record; +       +      if (CXXRecordDecl *InstRecord = dyn_cast<CXXRecordDecl>(DC)) { +        // Check whether we're in the process of instantiating a class template +        // specialization of the template we're mapping. +        if (ClassTemplateSpecializationDecl *InstSpec +                      = dyn_cast<ClassTemplateSpecializationDecl>(InstRecord)){ +          ClassTemplateDecl *SpecTemplate = InstSpec->getSpecializedTemplate(); +          if (ClassTemplate && isInstantiationOf(ClassTemplate, SpecTemplate)) +            return InstRecord; +        } +       +        // Check whether we're in the process of instantiating a member class. +        if (isInstantiationOf(Record, InstRecord)) +          return InstRecord;        } - -      // We are performing "partial" template instantiation to create -      // the member declarations for the members of a class template -      // specialization. Therefore, D is actually referring to something -      // in the current instantiation. Look through the current -      // context, which contains actual instantiations, to find the -      // instantiation of the "current instantiation" that D refers -      // to. -      bool SawNonDependentContext = false; -      for (DeclContext *DC = CurContext; !DC->isFileContext(); -           DC = DC->getParent()) { -        if (ClassTemplateSpecializationDecl *Spec -                          = dyn_cast<ClassTemplateSpecializationDecl>(DC)) -          if (isInstantiationOf(ClassTemplate, -                                Spec->getSpecializedTemplate())) -            return Spec; - -        if (!DC->isDependentContext()) -          SawNonDependentContext = true; +       +       +      // Move to the outer template scope. +      if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) { +        if (FD->getFriendObjectKind() && FD->getDeclContext()->isFileContext()){ +          DC = FD->getLexicalDeclContext(); +          continue; +        }        } - -      // We're performing "instantiation" of a member of the current -      // instantiation while we are type-checking the -      // definition. Compute the declaration context and return that. -      assert(!SawNonDependentContext && -             "No dependent context while instantiating record"); -      DeclContext *DC = computeDeclContext(T); -      assert(DC && -             "Unable to find declaration for the current instantiation"); -      return cast<CXXRecordDecl>(DC); +       +      DC = DC->getParent();      }      // Fall through to deal with other dependent record types (e.g., @@ -3260,6 +3300,20 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,            << D->getDeclName()            << Context.getTypeDeclType(cast<CXXRecordDecl>(ParentDC));          Diag(D->getLocation(), diag::note_non_instantiated_member_here); +      } else if (EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) { +        // This enumeration constant was found when the template was defined, +        // but can't be found in the instantiation. This can happen if an +        // unscoped enumeration member is explicitly specialized. +        EnumDecl *Enum = cast<EnumDecl>(ED->getLexicalDeclContext()); +        EnumDecl *Spec = cast<EnumDecl>(FindInstantiatedDecl(Loc, Enum, +                                                             TemplateArgs)); +        assert(Spec->getTemplateSpecializationKind() == +                 TSK_ExplicitSpecialization); +        Diag(Loc, diag::err_enumerator_does_not_exist) +          << D->getDeclName() +          << Context.getTypeDeclType(cast<TypeDecl>(Spec->getDeclContext())); +        Diag(Spec->getLocation(), diag::note_enum_specialized_here) +          << Context.getTypeDeclType(Spec);        } else {          // We should have found something, but didn't.          llvm_unreachable("Unable to find instantiation of declaration!"); @@ -3312,12 +3366,12 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {      // Don't try to instantiate declarations if the most recent redeclaration      // is invalid. -    if (Var->getMostRecentDeclaration()->isInvalidDecl()) +    if (Var->getMostRecentDecl()->isInvalidDecl())        continue;      // Check if the most recent declaration has changed the specialization kind      // and removed the need for implicit instantiation. -    switch (Var->getMostRecentDeclaration()->getTemplateSpecializationKind()) { +    switch (Var->getMostRecentDecl()->getTemplateSpecializationKind()) {      case TSK_Undeclared:        llvm_unreachable("Cannot instantitiate an undeclared specialization.");      case TSK_ExplicitInstantiationDeclaration: @@ -3326,7 +3380,7 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {      case TSK_ExplicitInstantiationDefinition:        // We only need an instantiation if the pending instantiation *is* the        // explicit instantiation. -      if (Var != Var->getMostRecentDeclaration()) continue; +      if (Var != Var->getMostRecentDecl()) continue;      case TSK_ImplicitInstantiation:        break;      }  | 
