diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 874 |
1 files changed, 588 insertions, 286 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 1c7869f..c0150c0 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -25,85 +25,6 @@ using namespace clang; -namespace { - class TemplateDeclInstantiator - : public DeclVisitor<TemplateDeclInstantiator, Decl *> { - Sema &SemaRef; - DeclContext *Owner; - const MultiLevelTemplateArgumentList &TemplateArgs; - - public: - TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, - const MultiLevelTemplateArgumentList &TemplateArgs) - : SemaRef(SemaRef), Owner(Owner), TemplateArgs(TemplateArgs) { } - - // FIXME: Once we get closer to completion, replace these manually-written - // declarations with automatically-generated ones from - // clang/AST/DeclNodes.inc. - Decl *VisitTranslationUnitDecl(TranslationUnitDecl *D); - Decl *VisitNamespaceDecl(NamespaceDecl *D); - Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - Decl *VisitTypedefDecl(TypedefDecl *D); - Decl *VisitVarDecl(VarDecl *D); - Decl *VisitAccessSpecDecl(AccessSpecDecl *D); - Decl *VisitFieldDecl(FieldDecl *D); - Decl *VisitStaticAssertDecl(StaticAssertDecl *D); - Decl *VisitEnumDecl(EnumDecl *D); - Decl *VisitEnumConstantDecl(EnumConstantDecl *D); - Decl *VisitFriendDecl(FriendDecl *D); - Decl *VisitFunctionDecl(FunctionDecl *D, - TemplateParameterList *TemplateParams = 0); - Decl *VisitCXXRecordDecl(CXXRecordDecl *D); - Decl *VisitCXXMethodDecl(CXXMethodDecl *D, - TemplateParameterList *TemplateParams = 0); - Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D); - Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D); - Decl *VisitCXXConversionDecl(CXXConversionDecl *D); - ParmVarDecl *VisitParmVarDecl(ParmVarDecl *D); - Decl *VisitClassTemplateDecl(ClassTemplateDecl *D); - Decl *VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D); - Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *D); - Decl *VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); - Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); - Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D); - Decl *VisitUsingDecl(UsingDecl *D); - Decl *VisitUsingShadowDecl(UsingShadowDecl *D); - Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); - Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); - - // Base case. FIXME: Remove once we can instantiate everything. - Decl *VisitDecl(Decl *D) { - unsigned DiagID = SemaRef.getDiagnostics().getCustomDiagID( - Diagnostic::Error, - "cannot instantiate %0 yet"); - SemaRef.Diag(D->getLocation(), DiagID) - << D->getDeclKindName(); - - return 0; - } - - // Helper functions for instantiating methods. - TypeSourceInfo *SubstFunctionType(FunctionDecl *D, - llvm::SmallVectorImpl<ParmVarDecl *> &Params); - bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl); - bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl); - - TemplateParameterList * - SubstTemplateParams(TemplateParameterList *List); - - bool SubstQualifier(const DeclaratorDecl *OldDecl, - DeclaratorDecl *NewDecl); - bool SubstQualifier(const TagDecl *OldDecl, - TagDecl *NewDecl); - - bool InstantiateClassTemplatePartialSpecialization( - ClassTemplateDecl *ClassTemplate, - ClassTemplatePartialSpecializationDecl *PartialSpec); - }; -} - bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl, DeclaratorDecl *NewDecl) { NestedNameSpecifier *OldQual = OldDecl->getQualifier(); @@ -151,15 +72,15 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, if (Aligned->isAlignmentExpr()) { ExprResult Result = SubstExpr(Aligned->getAlignmentExpr(), - TemplateArgs); + TemplateArgs); if (!Result.isInvalid()) AddAlignedAttr(Aligned->getLocation(), New, Result.takeAs<Expr>()); } else { TypeSourceInfo *Result = SubstType(Aligned->getAlignmentType(), - TemplateArgs, - Aligned->getLocation(), - DeclarationName()); + TemplateArgs, + Aligned->getLocation(), + DeclarationName()); if (Result) AddAlignedAttr(Aligned->getLocation(), New, Result); } @@ -180,6 +101,14 @@ TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) { } Decl * +TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { + LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier()); + Owner->addDecl(Inst); + return Inst; +} + +Decl * TemplateDeclInstantiator::VisitNamespaceDecl(NamespaceDecl *D) { assert(false && "Namespaces cannot be instantiated"); return D; @@ -222,13 +151,15 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { if (Invalid) Typedef->setInvalidDecl(); - if (const TagType *TT = DI->getType()->getAs<TagType>()) { - TagDecl *TD = TT->getDecl(); - - // If the TagDecl that the TypedefDecl points to is an anonymous decl - // keep track of the TypedefDecl. - if (!TD->getIdentifier() && !TD->getTypedefForAnonDecl()) - TD->setTypedefForAnonDecl(Typedef); + // If the old typedef was the name for linkage purposes of an anonymous + // tag decl, re-establish that relationship for the new typedef. + if (const TagType *oldTagType = D->getUnderlyingType()->getAs<TagType>()) { + TagDecl *oldTag = oldTagType->getDecl(); + if (oldTag->getTypedefForAnonDecl() == D) { + TagDecl *newTag = DI->getType()->castAs<TagType>()->getDecl(); + assert(!newTag->getIdentifier() && !newTag->getTypedefForAnonDecl()); + newTag->setTypedefForAnonDecl(Typedef); + } } if (TypedefDecl *Prev = D->getPreviousDeclaration()) { @@ -245,35 +176,6 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { return Typedef; } -/// \brief Instantiate the arguments provided as part of initialization. -/// -/// \returns true if an error occurred, false otherwise. -static bool InstantiateInitializationArguments(Sema &SemaRef, - Expr **Args, unsigned NumArgs, - const MultiLevelTemplateArgumentList &TemplateArgs, - llvm::SmallVectorImpl<SourceLocation> &FakeCommaLocs, - ASTOwningVector<Expr*> &InitArgs) { - for (unsigned I = 0; I != NumArgs; ++I) { - // When we hit the first defaulted argument, break out of the loop: - // we don't pass those default arguments on. - if (Args[I]->isDefaultArgument()) - break; - - ExprResult Arg = SemaRef.SubstExpr(Args[I], TemplateArgs); - if (Arg.isInvalid()) - return true; - - Expr *ArgExpr = (Expr *)Arg.get(); - InitArgs.push_back(Arg.release()); - - // FIXME: We're faking all of the comma locations. Do we need them? - FakeCommaLocs.push_back( - SemaRef.PP.getLocForEndOfToken(ArgExpr->getLocEnd())); - } - - return false; -} - /// \brief Instantiate an initializer, breaking it into separate /// initialization arguments. /// @@ -290,8 +192,7 @@ static bool InstantiateInitializationArguments(Sema &SemaRef, static bool InstantiateInitializer(Sema &S, Expr *Init, const MultiLevelTemplateArgumentList &TemplateArgs, SourceLocation &LParenLoc, - llvm::SmallVector<SourceLocation, 4> &CommaLocs, - ASTOwningVector<Expr*> &NewArgs, + ASTOwningVector<Expr*> &NewArgs, SourceLocation &RParenLoc) { NewArgs.clear(); LParenLoc = SourceLocation(); @@ -300,7 +201,7 @@ static bool InstantiateInitializer(Sema &S, Expr *Init, if (!Init) return false; - if (CXXExprWithTemporaries *ExprTemp = dyn_cast<CXXExprWithTemporaries>(Init)) + if (ExprWithCleanups *ExprTemp = dyn_cast<ExprWithCleanups>(Init)) Init = ExprTemp->getSubExpr(); while (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(Init)) @@ -312,24 +213,19 @@ static bool InstantiateInitializer(Sema &S, Expr *Init, if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { LParenLoc = ParenList->getLParenLoc(); RParenLoc = ParenList->getRParenLoc(); - return InstantiateInitializationArguments(S, ParenList->getExprs(), - ParenList->getNumExprs(), - TemplateArgs, CommaLocs, - NewArgs); + return S.SubstExprs(ParenList->getExprs(), ParenList->getNumExprs(), + true, TemplateArgs, NewArgs); } if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) { if (!isa<CXXTemporaryObjectExpr>(Construct)) { - if (InstantiateInitializationArguments(S, - Construct->getArgs(), - Construct->getNumArgs(), - TemplateArgs, - CommaLocs, NewArgs)) + if (S.SubstExprs(Construct->getArgs(), Construct->getNumArgs(), true, + TemplateArgs, NewArgs)) return true; // FIXME: Fake locations! LParenLoc = S.PP.getLocForEndOfToken(Init->getLocStart()); - RParenLoc = CommaLocs.empty()? LParenLoc : CommaLocs.back(); + RParenLoc = LParenLoc; return false; } } @@ -358,6 +254,12 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { if (!DI) return 0; + if (DI->getType()->isFunctionType()) { + SemaRef.Diag(D->getLocation(), diag::err_variable_instantiates_to_function) + << D->isStaticDataMember() << DI->getType(); + return 0; + } + // Build the instantiated declaration VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier(), @@ -419,24 +321,24 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // Instantiate the initializer. SourceLocation LParenLoc, RParenLoc; - llvm::SmallVector<SourceLocation, 4> CommaLocs; ASTOwningVector<Expr*> InitArgs(SemaRef); if (!InstantiateInitializer(SemaRef, D->getInit(), TemplateArgs, LParenLoc, - CommaLocs, InitArgs, RParenLoc)) { - // Attach the initializer to the declaration. - if (D->hasCXXDirectInitializer()) { + InitArgs, RParenLoc)) { + bool TypeMayContainAuto = true; + // Attach the initializer to the declaration, if we have one. + if (InitArgs.size() == 0) + SemaRef.ActOnUninitializedDecl(Var, TypeMayContainAuto); + else if (D->hasCXXDirectInitializer()) { // Add the direct initializer to the declaration. SemaRef.AddCXXDirectInitializerToDecl(Var, LParenLoc, move_arg(InitArgs), - CommaLocs.data(), - RParenLoc); - } else if (InitArgs.size() == 1) { - Expr *Init = InitArgs.take()[0]; - SemaRef.AddInitializerToDecl(Var, Init, false); + RParenLoc, + TypeMayContainAuto); } else { - assert(InitArgs.size() == 0); - SemaRef.ActOnUninitializedDecl(Var, false); + assert(InitArgs.size() == 1); + Expr *Init = InitArgs.take()[0]; + SemaRef.AddInitializerToDecl(Var, Init, false, TypeMayContainAuto); } } else { // FIXME: Not too happy about invalidating the declaration @@ -540,6 +442,30 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { return Field; } +Decl *TemplateDeclInstantiator::VisitIndirectFieldDecl(IndirectFieldDecl *D) { + NamedDecl **NamedChain = + new (SemaRef.Context)NamedDecl*[D->getChainingSize()]; + + int i = 0; + for (IndirectFieldDecl::chain_iterator PI = + D->chain_begin(), PE = D->chain_end(); + PI != PE; ++PI) + NamedChain[i++] = (SemaRef.FindInstantiatedDecl(D->getLocation(), + *PI, TemplateArgs)); + + QualType T = cast<FieldDecl>(NamedChain[i-1])->getType(); + IndirectFieldDecl* IndirectField + = IndirectFieldDecl::Create(SemaRef.Context, Owner, D->getLocation(), + D->getIdentifier(), T, + NamedChain, D->getChainingSize()); + + + IndirectField->setImplicit(D->isImplicit()); + IndirectField->setAccess(D->getAccess()); + Owner->addDecl(IndirectField); + return IndirectField; +} + Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { // Handle friend type expressions by simply substituting template // parameters into the pattern type and checking the result. @@ -555,6 +481,7 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { return 0; FD->setAccess(AS_public); + FD->setUnsupportedFriend(D->isUnsupportedFriend()); Owner->addDecl(FD); return FD; } @@ -573,6 +500,7 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) { FriendDecl::Create(SemaRef.Context, Owner, D->getLocation(), cast<NamedDecl>(NewND), D->getFriendLoc()); FD->setAccess(AS_public); + FD->setUnsupportedFriend(D->isUnsupportedFriend()); Owner->addDecl(FD); return FD; } @@ -589,7 +517,7 @@ Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) { return 0; ExprResult Message(D->getMessage()); - D->getMessage()->Retain(); + D->getMessage(); return SemaRef.ActOnStaticAssertDeclaration(D->getLocation(), InstantiatedAssertExpr.get(), Message.get()); @@ -599,7 +527,31 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { EnumDecl *Enum = EnumDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getIdentifier(), D->getTagKeywordLoc(), - /*PrevDecl=*/0); + /*PrevDecl=*/0, D->isScoped(), + D->isScopedUsingClassTag(), D->isFixed()); + if (D->isFixed()) { + 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()) + Enum->setIntegerType(SemaRef.Context.IntTy); + } + else { + assert(!D->getIntegerType()->isDependentType() + && "Dependent type without type source info"); + Enum->setIntegerType(D->getIntegerType()); + } + } + + SemaRef.InstantiateAttrs(TemplateArgs, D, Enum); + Enum->setInstantiationOfMemberEnum(D); Enum->setAccess(D->getAccess()); if (SubstQualifier(D, Enum)) return 0; @@ -644,6 +596,8 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { } if (EnumConst) { + SemaRef.InstantiateAttrs(TemplateArgs, *EC, EnumConst); + EnumConst->setAccess(Enum->getAccess()); Enum->addDecl(EnumConst); Enumerators.push_back(EnumConst); @@ -699,6 +653,15 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { CXXRecordDecl *PrevDecl = 0; ClassTemplateDecl *PrevClassTemplate = 0; + if (!isFriend && Pattern->getPreviousDeclaration()) { + DeclContext::lookup_result Found = Owner->lookup(Pattern->getDeclName()); + if (Found.first != Found.second) { + PrevClassTemplate = dyn_cast<ClassTemplateDecl>(*Found.first); + if (PrevClassTemplate) + PrevDecl = PrevClassTemplate->getTemplatedDecl(); + } + } + // If this isn't a friend, then it's a member template, in which // case we just want to build the instantiation in the // specialization. If it is a friend, we want to build it in @@ -813,7 +776,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { // friend target decl? } else { Inst->setAccess(D->getAccess()); - Inst->setInstantiatedFromMemberTemplate(D); + if (!PrevClassTemplate) + Inst->setInstantiatedFromMemberTemplate(D); } // Trigger creation of the type for the instantiation. @@ -827,14 +791,18 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { } Owner->addDecl(Inst); - - // Instantiate all of the partial specializations of this member class - // template. - llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; - D->getPartialSpecializations(PartialSpecs); - for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) - InstantiateClassTemplatePartialSpecialization(Inst, PartialSpecs[I]); - + + if (!PrevClassTemplate) { + // Queue up any out-of-line partial specializations of this member + // class template; the client will force their instantiation once + // the enclosing class has been instantiated. + llvm::SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; + D->getPartialSpecializations(PartialSpecs); + for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) + if (PartialSpecs[I]->isOutOfLine()) + OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I])); + } + return Inst; } @@ -855,7 +823,11 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( if (!InstClassTemplate) return 0; - return InstClassTemplate->findPartialSpecInstantiatedFromMember(D); + if (ClassTemplatePartialSpecializationDecl *Result + = InstClassTemplate->findPartialSpecInstantiatedFromMember(D)) + return Result; + + return InstantiateClassTemplatePartialSpecialization(InstClassTemplate, D); } Decl * @@ -1040,7 +1012,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // Attach the parameters for (unsigned P = 0; P < Params.size(); ++P) - Params[P]->setOwningFunction(Function); + if (Params[P]) + Params[P]->setOwningFunction(Function); Function->setParams(Params.data(), Params.size()); SourceLocation InstantiateAtPOI; @@ -1078,7 +1051,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, std::pair<const TemplateArgument *, unsigned> Innermost = TemplateArgs.getInnermost(); Function->setFunctionTemplateSpecialization(FunctionTemplate, - new (SemaRef.Context) TemplateArgumentList(SemaRef.Context, + TemplateArgumentList::CreateCopy(SemaRef.Context, Innermost.first, Innermost.second), InsertPos); @@ -1092,7 +1065,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Function->setInvalidDecl(); bool Redeclaration = false; - bool OverloadableAttrRequired = false; bool isExplicitSpecialization = false; LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(), @@ -1108,13 +1080,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, // Instantiate the explicit template arguments. TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(), Info->getRAngleLoc()); - for (unsigned I = 0, E = Info->getNumTemplateArgs(); I != E; ++I) { - TemplateArgumentLoc Loc; - if (SemaRef.Subst(Info->getTemplateArg(I), Loc, TemplateArgs)) - return 0; - - ExplicitArgs.addArgument(Loc); - } + if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(), + ExplicitArgs, TemplateArgs)) + return 0; // Map the candidate templates to their instantiations. for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) { @@ -1148,8 +1116,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous, - isExplicitSpecialization, Redeclaration, - /*FIXME:*/OverloadableAttrRequired); + isExplicitSpecialization, Redeclaration); NamedDecl *PrincipalDecl = (TemplateParams ? cast<NamedDecl>(FunctionTemplate) @@ -1256,6 +1223,20 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); + // Instantiate enclosing template arguments for friends. + llvm::SmallVector<TemplateParameterList *, 4> TempParamLists; + unsigned NumTempParamLists = 0; + if (isFriend && (NumTempParamLists = D->getNumTemplateParameterLists())) { + TempParamLists.set_size(NumTempParamLists); + for (unsigned I = 0; I != NumTempParamLists; ++I) { + TemplateParameterList *TempParams = D->getTemplateParameterList(I); + TemplateParameterList *InstParams = SubstTemplateParams(TempParams); + if (!InstParams) + return NULL; + TempParamLists[I] = InstParams; + } + } + llvm::SmallVector<ParmVarDecl *, 4> Params; TypeSourceInfo *TInfo = D->getTypeSourceInfo(); TInfo = SubstFunctionType(D, Params); @@ -1263,25 +1244,22 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, return 0; QualType T = TInfo->getType(); - // \brief If the type of this function is not *directly* a function - // type, then we're instantiating the a function that was declared - // via a typedef, e.g., + // \brief If the type of this function, after ignoring parentheses, + // is not *directly* a function type, then we're instantiating a function + // that was declared via a typedef, e.g., // // typedef int functype(int, int); // functype func; // // In this case, we'll just go instantiate the ParmVarDecls that we // synthesized in the method declaration. - if (!isa<FunctionProtoType>(T)) { + if (!isa<FunctionProtoType>(T.IgnoreParens())) { assert(!Params.size() && "Instantiating type could not yield parameters"); - for (unsigned I = 0, N = D->getNumParams(); I != N; ++I) { - ParmVarDecl *P = SemaRef.SubstParmVarDecl(D->getParamDecl(I), - TemplateArgs); - if (!P) - return 0; - - Params.push_back(P); - } + llvm::SmallVector<QualType, 4> ParamTypes; + if (SemaRef.SubstParmTypes(D->getLocation(), D->param_begin(), + D->getNumParams(), TemplateArgs, ParamTypes, + &Params)) + return 0; } NestedNameSpecifier *Qualifier = D->getQualifier(); @@ -1299,6 +1277,9 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, SS.setScopeRep(Qualifier); SS.setRange(D->getQualifierRange()); DC = SemaRef.computeDeclContext(SS); + + if (DC && SemaRef.RequireCompleteDeclContext(SS, DC)) + return 0; } else { DC = SemaRef.FindInstantiatedContext(D->getLocation(), D->getDeclContext(), @@ -1321,7 +1302,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, false); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, - NameInfo, T, + NameInfo, T, TInfo, Destructor->isInlineSpecified(), false); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { @@ -1369,9 +1350,9 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, std::pair<const TemplateArgument *, unsigned> Innermost = TemplateArgs.getInnermost(); Method->setFunctionTemplateSpecialization(FunctionTemplate, - new (SemaRef.Context) TemplateArgumentList(SemaRef.Context, - Innermost.first, - Innermost.second), + TemplateArgumentList::CreateCopy(SemaRef.Context, + Innermost.first, + Innermost.second), InsertPos); } else if (!isFriend) { // Record that this is an instantiation of a member function. @@ -1382,6 +1363,11 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, // out-of-line, the instantiation will have the same lexical // context (which will be a namespace scope) as the template. if (isFriend) { + if (NumTempParamLists) + Method->setTemplateParameterListsInfo(SemaRef.Context, + NumTempParamLists, + TempParamLists.data()); + Method->setLexicalDeclContext(Owner); Method->setObjectOfFriendDecl(true); } else if (D->isOutOfLine()) @@ -1410,15 +1396,15 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, } bool Redeclaration = false; - bool OverloadableAttrRequired = false; - SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration, - /*FIXME:*/OverloadableAttrRequired); + SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration); if (D->isPure()) SemaRef.CheckPureMethod(Method, SourceRange()); Method->setAccess(D->getAccess()); + SemaRef.CheckOverrideControl(Method); + if (FunctionTemplate) { // If there's a function template, let our caller handle it. } else if (Method->isInvalidDecl() && !Previous.empty()) { @@ -1449,7 +1435,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { } ParmVarDecl *TemplateDeclInstantiator::VisitParmVarDecl(ParmVarDecl *D) { - return SemaRef.SubstParmVarDecl(D, TemplateArgs); + return SemaRef.SubstParmVarDecl(D, TemplateArgs, llvm::Optional<unsigned>()); } Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( @@ -1462,7 +1448,7 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), TTPT->getDepth() - TemplateArgs.getNumLevels(), - TTPT->getIndex(),TTPT->getName(), + TTPT->getIndex(), D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); @@ -1479,33 +1465,140 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( NonTypeTemplateParmDecl *D) { // Substitute into the type of the non-type template parameter. + TypeLoc TL = D->getTypeSourceInfo()->getTypeLoc(); + llvm::SmallVector<TypeSourceInfo *, 4> ExpandedParameterPackTypesAsWritten; + llvm::SmallVector<QualType, 4> ExpandedParameterPackTypes; + bool IsExpandedParameterPack = false; + TypeSourceInfo *DI; QualType T; - TypeSourceInfo *DI = D->getTypeSourceInfo(); - if (DI) { - DI = SemaRef.SubstType(DI, TemplateArgs, D->getLocation(), - D->getDeclName()); - if (DI) T = DI->getType(); - } else { - T = SemaRef.SubstType(D->getType(), TemplateArgs, D->getLocation(), - D->getDeclName()); - DI = 0; - } - if (T.isNull()) - return 0; - - // Check that this type is acceptable for a non-type template parameter. bool Invalid = false; - T = SemaRef.CheckNonTypeTemplateParameterType(T, D->getLocation()); - if (T.isNull()) { - T = SemaRef.Context.IntTy; - Invalid = true; + + if (D->isExpandedParameterPack()) { + // The non-type template parameter pack is an already-expanded pack + // expansion of types. Substitute into each of the expanded types. + ExpandedParameterPackTypes.reserve(D->getNumExpansionTypes()); + ExpandedParameterPackTypesAsWritten.reserve(D->getNumExpansionTypes()); + for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { + TypeSourceInfo *NewDI =SemaRef.SubstType(D->getExpansionTypeSourceInfo(I), + TemplateArgs, + D->getLocation(), + D->getDeclName()); + if (!NewDI) + return 0; + + ExpandedParameterPackTypesAsWritten.push_back(NewDI); + QualType NewT =SemaRef.CheckNonTypeTemplateParameterType(NewDI->getType(), + D->getLocation()); + if (NewT.isNull()) + return 0; + ExpandedParameterPackTypes.push_back(NewT); + } + + IsExpandedParameterPack = true; + DI = D->getTypeSourceInfo(); + T = DI->getType(); + } else if (isa<PackExpansionTypeLoc>(TL)) { + // The non-type template parameter pack's type is a pack expansion of types. + // Determine whether we need to expand this parameter pack into separate + // types. + PackExpansionTypeLoc Expansion = cast<PackExpansionTypeLoc>(TL); + TypeLoc Pattern = Expansion.getPatternLoc(); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + llvm::Optional<unsigned> OrigNumExpansions + = Expansion.getTypePtr()->getNumExpansions(); + llvm::Optional<unsigned> NumExpansions = OrigNumExpansions; + if (SemaRef.CheckParameterPacksForExpansion(Expansion.getEllipsisLoc(), + Pattern.getSourceRange(), + Unexpanded.data(), + Unexpanded.size(), + TemplateArgs, + Expand, RetainExpansion, + NumExpansions)) + return 0; + + if (Expand) { + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); + TypeSourceInfo *NewDI = SemaRef.SubstType(Pattern, TemplateArgs, + D->getLocation(), + D->getDeclName()); + if (!NewDI) + return 0; + + ExpandedParameterPackTypesAsWritten.push_back(NewDI); + QualType NewT = SemaRef.CheckNonTypeTemplateParameterType( + NewDI->getType(), + D->getLocation()); + if (NewT.isNull()) + return 0; + ExpandedParameterPackTypes.push_back(NewT); + } + + // Note that we have an expanded parameter pack. The "type" of this + // expanded parameter pack is the original expansion type, but callers + // will end up using the expanded parameter pack types for type-checking. + IsExpandedParameterPack = true; + DI = D->getTypeSourceInfo(); + T = DI->getType(); + } else { + // We cannot fully expand the pack expansion now, so substitute into the + // pattern and create a new pack expansion type. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); + TypeSourceInfo *NewPattern = SemaRef.SubstType(Pattern, TemplateArgs, + D->getLocation(), + D->getDeclName()); + if (!NewPattern) + return 0; + + DI = SemaRef.CheckPackExpansion(NewPattern, Expansion.getEllipsisLoc(), + NumExpansions); + if (!DI) + return 0; + + T = DI->getType(); + } + } else { + // Simple case: substitution into a parameter that is not a parameter pack. + DI = SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs, + D->getLocation(), D->getDeclName()); + if (!DI) + return 0; + + // Check that this type is acceptable for a non-type template parameter. + bool Invalid = false; + T = SemaRef.CheckNonTypeTemplateParameterType(DI->getType(), + D->getLocation()); + if (T.isNull()) { + T = SemaRef.Context.IntTy; + Invalid = true; + } } - NonTypeTemplateParmDecl *Param - = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), + NonTypeTemplateParmDecl *Param; + if (IsExpandedParameterPack) + Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, + D->getLocation(), D->getDepth() - TemplateArgs.getNumLevels(), - D->getPosition(), D->getIdentifier(), T, - DI); + D->getPosition(), + D->getIdentifier(), T, + DI, + ExpandedParameterPackTypes.data(), + ExpandedParameterPackTypes.size(), + ExpandedParameterPackTypesAsWritten.data()); + else + Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner, + D->getLocation(), + D->getDepth() - TemplateArgs.getNumLevels(), + D->getPosition(), + D->getIdentifier(), T, + D->isParameterPack(), DI); + if (Invalid) Param->setInvalidDecl(); @@ -1536,8 +1629,8 @@ TemplateDeclInstantiator::VisitTemplateTemplateParmDecl( TemplateTemplateParmDecl *Param = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner, D->getLocation(), D->getDepth() - TemplateArgs.getNumLevels(), - D->getPosition(), D->getIdentifier(), - InstParams); + D->getPosition(), D->isParameterPack(), + D->getIdentifier(), InstParams); Param->setDefaultArgument(D->getDefaultArgument(), false); // Introduce this template parameter's instantiation into the instantiation @@ -1562,8 +1655,24 @@ Decl *TemplateDeclInstantiator::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { } Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { - // The nested name specifier is non-dependent, so no transformation - // is required. The same holds for the name info. + + // The nested name specifier may be dependent, for example + // template <typename T> struct t { + // struct s1 { T f1(); }; + // struct s2 : s1 { using s1::f1; }; + // }; + // template struct t<int>; + // Here, in using s1::f1, s1 refers to t<T>::s1; + // we need to substitute for t<int>::s1. + NestedNameSpecifier *NNS = + SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameDecl(), + D->getNestedNameRange(), + TemplateArgs); + if (!NNS) + return 0; + + // The name info is non-dependent, so no transformation + // is required. DeclarationNameInfo NameInfo = D->getNameInfo(); // We only need to do redeclaration lookups if we're in a class @@ -1577,12 +1686,12 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner, D->getNestedNameRange(), D->getUsingLocation(), - D->getTargetNestedNameDecl(), + NNS, NameInfo, D->isTypeName()); CXXScopeSpec SS; - SS.setScopeRep(D->getTargetNestedNameDecl()); + SS.setScopeRep(NNS); SS.setRange(D->getNestedNameRange()); if (CheckRedeclaration) { @@ -1746,8 +1855,9 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { /// \param PartialSpec the (uninstantiated) class template partial /// specialization that we are instantiating. /// -/// \returns true if there was an error, false otherwise. -bool +/// \returns The instantiated partial specialization, if successful; otherwise, +/// NULL to indicate an error. +ClassTemplatePartialSpecializationDecl * TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( ClassTemplateDecl *ClassTemplate, ClassTemplatePartialSpecializationDecl *PartialSpec) { @@ -1761,47 +1871,39 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( TemplateParameterList *TempParams = PartialSpec->getTemplateParameters(); TemplateParameterList *InstParams = SubstTemplateParams(TempParams); if (!InstParams) - return true; + return 0; // Substitute into the template arguments of the class template partial // specialization. - const TemplateArgumentLoc *PartialSpecTemplateArgs - = PartialSpec->getTemplateArgsAsWritten(); - unsigned N = PartialSpec->getNumTemplateArgsAsWritten(); - TemplateArgumentListInfo InstTemplateArgs; // no angle locations - for (unsigned I = 0; I != N; ++I) { - TemplateArgumentLoc Loc; - if (SemaRef.Subst(PartialSpecTemplateArgs[I], Loc, TemplateArgs)) - return true; - InstTemplateArgs.addArgument(Loc); - } + if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(), + PartialSpec->getNumTemplateArgsAsWritten(), + InstTemplateArgs, TemplateArgs)) + return 0; - // Check that the template argument list is well-formed for this // class template. - TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), - InstTemplateArgs.size()); + llvm::SmallVector<TemplateArgument, 4> Converted; if (SemaRef.CheckTemplateArgumentList(ClassTemplate, PartialSpec->getLocation(), InstTemplateArgs, false, Converted)) - return true; + return 0; // Figure out where to insert this class template partial specialization // in the member template's set of class template partial specializations. void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl - = ClassTemplate->findPartialSpecialization(Converted.getFlatArguments(), - Converted.flatSize(), InsertPos); + = ClassTemplate->findPartialSpecialization(Converted.data(), + Converted.size(), InsertPos); // Build the canonical type that describes the converted template // arguments of the class template partial specialization. QualType CanonType = SemaRef.Context.getTemplateSpecializationType(TemplateName(ClassTemplate), - Converted.getFlatArguments(), - Converted.flatSize()); + Converted.data(), + Converted.size()); // Build the fully-sugared type for this class template // specialization as the user wrote in the specialization @@ -1834,10 +1936,10 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // Outer<int, int> outer; // error: the partial specializations of Inner // // have the same signature. SemaRef.Diag(PartialSpec->getLocation(), diag::err_partial_spec_redeclared) - << WrittenTy; + << WrittenTy->getType(); SemaRef.Diag(PrevDecl->getLocation(), diag::note_prev_partial_spec_here) << SemaRef.Context.getTypeDeclType(PrevDecl); - return true; + return 0; } @@ -1849,7 +1951,8 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( PartialSpec->getLocation(), InstParams, ClassTemplate, - Converted, + Converted.data(), + Converted.size(), InstTemplateArgs, CanonType, 0, @@ -1864,7 +1967,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // Add this partial specialization to the set of class template partial // specializations. ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos); - return false; + return InstPartialSpec; } TypeSourceInfo* @@ -1882,25 +1985,47 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D, if (NewTInfo != OldTInfo) { // Get parameters from the new type info. - TypeLoc OldTL = OldTInfo->getTypeLoc(); + TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); if (FunctionProtoTypeLoc *OldProtoLoc = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) { - TypeLoc NewTL = NewTInfo->getTypeLoc(); + TypeLoc NewTL = NewTInfo->getTypeLoc().IgnoreParens(); FunctionProtoTypeLoc *NewProtoLoc = cast<FunctionProtoTypeLoc>(&NewTL); assert(NewProtoLoc && "Missing prototype?"); - for (unsigned i = 0, i_end = NewProtoLoc->getNumArgs(); i != i_end; ++i) { - // FIXME: Variadic templates will break this. - Params.push_back(NewProtoLoc->getArg(i)); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - OldProtoLoc->getArg(i), - NewProtoLoc->getArg(i)); + unsigned NewIdx = 0, NumNewParams = NewProtoLoc->getNumArgs(); + for (unsigned OldIdx = 0, NumOldParams = OldProtoLoc->getNumArgs(); + OldIdx != NumOldParams; ++OldIdx) { + ParmVarDecl *OldParam = OldProtoLoc->getArg(OldIdx); + if (!OldParam->isParameterPack() || + (NewIdx < NumNewParams && + NewProtoLoc->getArg(NewIdx)->isParameterPack())) { + // Simple case: normal parameter, or a parameter pack that's + // instantiated to a (still-dependent) parameter pack. + ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++); + Params.push_back(NewParam); + SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, + NewParam); + continue; + } + + // Parameter pack: make the instantiation an argument pack. + SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack( + OldParam); + unsigned NumArgumentsInExpansion + = SemaRef.getNumArgumentsInExpansion(OldParam->getType(), + TemplateArgs); + while (NumArgumentsInExpansion--) { + ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++); + Params.push_back(NewParam); + SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(OldParam, + NewParam); + } } } } else { // The function type itself was not dependent and therefore no // substitution occurred. However, we still need to instantiate // the function parameters themselves. - TypeLoc OldTL = OldTInfo->getTypeLoc(); + TypeLoc OldTL = OldTInfo->getTypeLoc().IgnoreParens(); if (FunctionProtoTypeLoc *OldProtoLoc = dyn_cast<FunctionProtoTypeLoc>(&OldTL)) { for (unsigned i = 0, i_end = OldProtoLoc->getNumArgs(); i != i_end; ++i) { @@ -1957,6 +2082,67 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, llvm::SmallVector<QualType, 4> Exceptions; for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) { // FIXME: Poor location information! + if (const PackExpansionType *PackExpansion + = Proto->getExceptionType(I)->getAs<PackExpansionType>()) { + // We have a pack expansion. Instantiate it. + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(), + Unexpanded); + assert(!Unexpanded.empty() && + "Pack expansion without parameter packs?"); + + bool Expand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions + = PackExpansion->getNumExpansions(); + if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(), + SourceRange(), + Unexpanded.data(), + Unexpanded.size(), + TemplateArgs, + Expand, + RetainExpansion, + NumExpansions)) + break; + + if (!Expand) { + // We can't expand this pack expansion into separate arguments yet; + // just substitute into the pattern and create a new pack expansion + // type. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); + QualType T = SemaRef.SubstType(PackExpansion->getPattern(), + TemplateArgs, + New->getLocation(), New->getDeclName()); + if (T.isNull()) + break; + + T = SemaRef.Context.getPackExpansionType(T, NumExpansions); + Exceptions.push_back(T); + continue; + } + + // Substitute into the pack expansion pattern for each template + bool Invalid = false; + for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx); + + QualType T = SemaRef.SubstType(PackExpansion->getPattern(), + TemplateArgs, + New->getLocation(), New->getDeclName()); + if (T.isNull()) { + Invalid = true; + break; + } + + Exceptions.push_back(T); + } + + if (Invalid) + break; + + continue; + } + QualType T = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs, New->getLocation(), New->getDeclName()); @@ -1969,19 +2155,20 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, // Rebuild the function type + FunctionProtoType::ExtProtoInfo EPI = Proto->getExtProtoInfo(); + EPI.HasExceptionSpec = Proto->hasExceptionSpec(); + EPI.HasAnyExceptionSpec = Proto->hasAnyExceptionSpec(); + EPI.NumExceptions = Exceptions.size(); + EPI.Exceptions = Exceptions.data(); + EPI.ExtInfo = Proto->getExtInfo(); + const FunctionProtoType *NewProto = New->getType()->getAs<FunctionProtoType>(); assert(NewProto && "Template instantiation without function prototype?"); New->setType(SemaRef.Context.getFunctionType(NewProto->getResultType(), NewProto->arg_type_begin(), NewProto->getNumArgs(), - NewProto->isVariadic(), - NewProto->getTypeQuals(), - Proto->hasExceptionSpec(), - Proto->hasAnyExceptionSpec(), - Exceptions.size(), - Exceptions.data(), - Proto->getExtInfo())); + EPI)); } SemaRef.InstantiateAttrs(TemplateArgs, Tmpl, New); @@ -2000,10 +2187,9 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, if (InitFunctionInstantiation(New, Tmpl)) return true; - CXXRecordDecl *Record = cast<CXXRecordDecl>(Owner); New->setAccess(Tmpl->getAccess()); if (Tmpl->isVirtualAsWritten()) - Record->setMethodAsVirtual(New); + New->setVirtualAsWritten(true); // FIXME: attributes // FIXME: New needs a pointer to Tmpl @@ -2084,9 +2270,12 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // 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. + llvm::SmallVector<VTableUse, 16> SavedVTableUses; std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; - if (Recursive) + if (Recursive) { + VTableUses.swap(SavedVTableUses); PendingInstantiations.swap(SavedPendingInstantiations); + } EnterExpressionEvaluationContext EvalContext(*this, Sema::PotentiallyEvaluated); @@ -2105,17 +2294,33 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // Introduce the instantiated function parameters into the local // instantiation scope, and set the parameter names to those used // in the template. + unsigned FParamIdx = 0; for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); - ParmVarDecl *FunctionParam = Function->getParamDecl(I); - FunctionParam->setDeclName(PatternParam->getDeclName()); - Scope.InstantiatedLocal(PatternParam, FunctionParam); + if (!PatternParam->isParameterPack()) { + // Simple case: not a parameter pack. + assert(FParamIdx < Function->getNumParams()); + ParmVarDecl *FunctionParam = Function->getParamDecl(I); + FunctionParam->setDeclName(PatternParam->getDeclName()); + Scope.InstantiatedLocal(PatternParam, FunctionParam); + ++FParamIdx; + continue; + } + + // Expand the parameter pack. + Scope.MakeInstantiatedLocalArgPack(PatternParam); + for (unsigned NumFParams = Function->getNumParams(); + FParamIdx < NumFParams; + ++FParamIdx) { + ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); + FunctionParam->setDeclName(PatternParam->getDeclName()); + Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam); + } } // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. - DeclContext *PreviousContext = CurContext; - CurContext = Function; + Sema::ContextRAII savedContext(*this, Function); MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(Function, 0, false, PatternDecl); @@ -2138,7 +2343,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, PerformDependentDiagnostics(PatternDecl, TemplateArgs); - CurContext = PreviousContext; + savedContext.pop(); DeclGroupRef DG(Function); Consumer.HandleTopLevelDecl(DG); @@ -2149,10 +2354,16 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, Scope.Exit(); if (Recursive) { + // Define any pending vtables. + DefineUsedVTables(); + // Instantiate any pending implicit instantiations found during the // instantiation of this template. PerformPendingInstantiations(); + // Restore the set of pending vtables. + VTableUses.swap(SavedVTableUses); + // Restore the set of pending implicit instantiations. PendingInstantiations.swap(SavedPendingInstantiations); } @@ -2233,13 +2444,13 @@ void Sema::InstantiateStaticDataMemberDefinition( // Enter the scope of this instantiation. We don't use // PushDeclContext because we don't have a scope. - DeclContext *PreviousContext = CurContext; - CurContext = Var->getDeclContext(); + ContextRAII previousContext(*this, Var->getDeclContext()); VarDecl *OldVar = Var; Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(), - getTemplateInstantiationArgs(Var))); - CurContext = PreviousContext; + getTemplateInstantiationArgs(Var))); + + previousContext.pop(); if (Var) { MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo(); @@ -2272,7 +2483,7 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, for (CXXConstructorDecl::init_const_iterator Inits = Tmpl->init_begin(), InitsEnd = Tmpl->init_end(); Inits != InitsEnd; ++Inits) { - CXXBaseOrMemberInitializer *Init = *Inits; + CXXCtorInitializer *Init = *Inits; // Only instantiate written initializers, let Sema re-construct implicit // ones. @@ -2281,11 +2492,75 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, SourceLocation LParenLoc, RParenLoc; ASTOwningVector<Expr*> NewArgs(*this); - llvm::SmallVector<SourceLocation, 4> CommaLocs; + + SourceLocation EllipsisLoc; + + if (Init->isPackExpansion()) { + // This is a pack expansion. We should expand it now. + TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc(); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + collectUnexpandedParameterPacks(BaseTL, Unexpanded); + bool ShouldExpand = false; + bool RetainExpansion = false; + llvm::Optional<unsigned> NumExpansions; + if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), + BaseTL.getSourceRange(), + Unexpanded.data(), + Unexpanded.size(), + TemplateArgs, ShouldExpand, + RetainExpansion, + NumExpansions)) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } + assert(ShouldExpand && "Partial instantiation of base initializer?"); + + // Loop over all of the arguments in the argument pack(s), + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); + + // Instantiate the initializer. + if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, + LParenLoc, NewArgs, RParenLoc)) { + AnyErrors = true; + break; + } + + // Instantiate the base type. + TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), + TemplateArgs, + Init->getSourceLocation(), + New->getDeclName()); + if (!BaseTInfo) { + AnyErrors = true; + break; + } + + // Build the initializer. + MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), + BaseTInfo, + (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getLParenLoc(), + Init->getRParenLoc(), + New->getParent(), + SourceLocation()); + if (NewInit.isInvalid()) { + AnyErrors = true; + break; + } + + NewInits.push_back(NewInit.get()); + NewArgs.clear(); + } + + continue; + } // Instantiate the initializer. if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, - LParenLoc, CommaLocs, NewArgs, RParenLoc)) { + LParenLoc, NewArgs, RParenLoc)) { AnyErrors = true; continue; } @@ -2307,24 +2582,30 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, NewArgs.size(), Init->getLParenLoc(), Init->getRParenLoc(), - New->getParent()); + New->getParent(), + EllipsisLoc); } else if (Init->isMemberInitializer()) { - FieldDecl *Member; - - // Is this an anonymous union? - if (FieldDecl *UnionInit = Init->getAnonUnionMember()) - Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMemberLocation(), - UnionInit, TemplateArgs)); - else - Member = cast<FieldDecl>(FindInstantiatedDecl(Init->getMemberLocation(), - Init->getMember(), - TemplateArgs)); + FieldDecl *Member = cast<FieldDecl>(FindInstantiatedDecl( + Init->getMemberLocation(), + Init->getMember(), + TemplateArgs)); NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), NewArgs.size(), Init->getSourceLocation(), Init->getLParenLoc(), Init->getRParenLoc()); + } else if (Init->isIndirectMemberInitializer()) { + IndirectFieldDecl *IndirectMember = + cast<IndirectFieldDecl>(FindInstantiatedDecl( + Init->getMemberLocation(), + Init->getIndirectMember(), TemplateArgs)); + + NewInit = BuildMemberInitializer(IndirectMember, (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getSourceLocation(), + Init->getLParenLoc(), + Init->getRParenLoc()); } if (NewInit.isInvalid()) { @@ -2589,7 +2870,27 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext())) { // D is a local of some kind. Look into the map of local // declarations to their instantiations. - return cast<NamedDecl>(CurrentInstantiationScope->getInstantiationOf(D)); + typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack; + llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found + = CurrentInstantiationScope->findInstantiationOf(D); + + if (Found) { + if (Decl *FD = Found->dyn_cast<Decl *>()) + return cast<NamedDecl>(FD); + + unsigned PackIdx = ArgumentPackSubstitutionIndex; + return cast<NamedDecl>((*Found->get<DeclArgumentPack *>())[PackIdx]); + } + + // If we didn't find the decl, then we must have a label decl that hasn't + // been found yet. Lazily instantiate it and return it now. + assert(isa<LabelDecl>(D)); + + Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); + assert(Inst && "Failed to instantiate label??"); + + CurrentInstantiationScope->InstantiatedLocal(D, Inst); + return cast<LabelDecl>(Inst); } if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { @@ -2693,6 +2994,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, if (!Tag->isBeingDefined() && RequireCompleteType(Loc, T, diag::err_incomplete_type)) return 0; + + ParentDC = Tag->getDecl(); } } @@ -2800,4 +3103,3 @@ void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, } } } - |