diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 51 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 19 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 12 |
4 files changed, 59 insertions, 27 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 419f59d588..a0c89f0fbd 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -522,6 +522,14 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, IdResolver.AddDecl(Param); } + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (DefaultArg && Ellipsis) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + DefaultArg = ParsedType(); + } + // Handle the default argument, if provided. if (DefaultArg) { TypeSourceInfo *DefaultTInfo; @@ -529,14 +537,6 @@ Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, assert(DefaultTInfo && "expected source information for type"); - // C++0x [temp.param]p9: - // A default template-argument may be specified for any kind of - // template-parameter that is not a template parameter pack. - if (Ellipsis) { - Diag(EqualLoc, diag::err_template_param_pack_default_arg); - return Param; - } - // Check for unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(Loc, DefaultTInfo, UPPC_DefaultArgument)) @@ -647,16 +647,16 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, IdResolver.AddDecl(Param); } + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (Default && IsParameterPack) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + Default = 0; + } + // Check the well-formedness of the default template argument, if provided. if (Default) { - // C++0x [temp.param]p9: - // A default template-argument may be specified for any kind of - // template-parameter that is not a template parameter pack. - if (IsParameterPack) { - Diag(EqualLoc, diag::err_template_param_pack_default_arg); - return Param; - } - // Check for unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument)) return Param; @@ -679,21 +679,24 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, Decl *Sema::ActOnTemplateTemplateParameter(Scope* S, SourceLocation TmpLoc, TemplateParamsTy *Params, + SourceLocation EllipsisLoc, IdentifierInfo *Name, SourceLocation NameLoc, unsigned Depth, unsigned Position, SourceLocation EqualLoc, - const ParsedTemplateArgument &Default) { + ParsedTemplateArgument Default) { assert(S->isTemplateParamScope() && "Template template parameter not in template parameter scope!"); // Construct the parameter object. + bool IsParameterPack = EllipsisLoc.isValid(); + // FIXME: Pack-ness is dropped TemplateTemplateParmDecl *Param = TemplateTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), NameLoc.isInvalid()? TmpLoc : NameLoc, - Depth, Position, Name, - Params); + Depth, Position, IsParameterPack, + Name, Params); // If the template template parameter has a name, then link the identifier // into the scope and lookup mechanisms. @@ -708,6 +711,14 @@ Decl *Sema::ActOnTemplateTemplateParameter(Scope* S, Param->setInvalidDecl(); } + // C++0x [temp.param]p9: + // A default template-argument may be specified for any kind of + // template-parameter that is not a template parameter pack. + if (IsParameterPack && !Default.isInvalid()) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + Default = ParsedTemplateArgument(); + } + if (!Default.isInvalid()) { // Check only that we have a template template argument. We don't want to // try to check well-formedness now, because our template template parameter @@ -1212,7 +1223,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // new declaration. SawDefaultArgument = true; // FIXME: We need to create a new kind of "default argument" - // expression that points to a previous template template + // expression that points to a previous non-type template // parameter. NewNonTypeParm->setDefaultArgument( OldNonTypeParm->getDefaultArgument(), diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 5d724f3b70..a256537068 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -697,9 +697,22 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { TTP->getPosition())) return D; - // FIXME: Variadic templates index substitution. - TemplateName Template - = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate(); + TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition()); + + if (TTP->isParameterPack()) { + assert(Arg.getKind() == TemplateArgument::Pack && + "Missing argument pack"); + + if (getSema().ArgumentPackSubstitutionIndex == -1) { + // FIXME: Variadic templates fun case. + getSema().Diag(Loc, diag::err_pack_expansion_mismatch_unsupported); + return 0; + } + + Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex]; + } + + TemplateName Template = Arg.getAsTemplate(); assert(!Template.isNull() && Template.getAsTemplateDecl() && "Wrong kind of template template argument"); return Template.getAsTemplateDecl(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 60a942ac2f..92521ae16e 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1542,8 +1542,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 diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 4e01ec2407..acb73144d9 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -78,7 +78,16 @@ namespace { return true; } - // FIXME: Record occurrences of template template parameter packs. + /// \brief Record occurrences of template template parameter packs. + bool TraverseTemplateName(TemplateName Template) { + if (TemplateTemplateParmDecl *TTP + = dyn_cast_or_null<TemplateTemplateParmDecl>( + Template.getAsTemplateDecl())) + if (TTP->isParameterPack()) + Unexpanded.push_back(std::make_pair(TTP, SourceLocation())); + + return inherited::TraverseTemplateName(Template); + } //------------------------------------------------------------------------ // Pruning the search for unexpanded parameter packs. @@ -556,7 +565,6 @@ ExprResult Sema::ActOnSizeofParameterPackExpr(Scope *S, SourceLocation RParenLoc) { // C++0x [expr.sizeof]p5: // The identifier in a sizeof... expression shall name a parameter pack. - LookupResult R(*this, &Name, NameLoc, LookupOrdinaryName); LookupName(R, S); |