TemplateArgument *Args;
unsigned NumArgs;
} Args;
+ struct {
+ void *Template;
+ bool PackExpansion;
+ } TemplateArg;
};
public:
Integer.Type = Type.getAsOpaquePtr();
}
- /// \brief Construct a template argument that is a template.
+ /// \brief Construct a template argument that is a template or a pack
+ /// expansion of templates.
///
/// This form of template argument is generally used for template template
/// parameters. However, the template name could be a dependent template
/// name that ends up being instantiated to a function template whose address
/// is taken.
- TemplateArgument(TemplateName Name) : Kind(Template) {
- TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
+ ///
+ /// \param Name The template name.
+ /// \param PackExpansion Whether this template argument is a pack expansion.
+ TemplateArgument(TemplateName Name, bool PackExpansion = false)
+ : Kind(Template)
+ {
+ TemplateArg.Template = Name.getAsVoidPointer();
+ TemplateArg.PackExpansion = PackExpansion;
}
/// \brief Construct a template argument that is an expression.
} else if (Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
Args.Args = Other.Args.Args;
- }
- else
+ } else if (Kind == Template) {
+ TemplateArg = Other.TemplateArg;
+ } else
TypeOrValue = Other.TypeOrValue;
}
} else if (Other.Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
Args.Args = Other.Args.Args;
+ } else if (Other.Kind == Template) {
+ TemplateArg = Other.TemplateArg;
} else {
TypeOrValue = Other.TypeOrValue;
}
if (Kind != Template)
return TemplateName();
- return TemplateName::getFromVoidPointer(
- reinterpret_cast<void *> (TypeOrValue));
+ return TemplateName::getFromVoidPointer(TemplateArg.Template);
}
/// \brief Retrieve the template argument as an integral value.
struct {
unsigned QualifierRange[2];
unsigned TemplateNameLoc;
+ unsigned EllipsisLoc;
} Template;
};
TemplateArgumentLocInfo(Expr *E) : Expression(E) {}
TemplateArgumentLocInfo(SourceRange QualifierRange,
- SourceLocation TemplateNameLoc)
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc)
{
Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
+ Template.EllipsisLoc = EllipsisLoc.getRawEncoding();
}
TypeSourceInfo *getAsTypeSourceInfo() const {
SourceLocation getTemplateNameLoc() const {
return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
}
+
+ SourceLocation getTemplateEllipsisLoc() const {
+ return SourceLocation::getFromRawEncoding(Template.EllipsisLoc);
+ }
};
/// Location wrapper for a TemplateArgument. TemplateArgument is to
TemplateArgumentLoc(const TemplateArgument &Argument,
SourceRange QualifierRange,
- SourceLocation TemplateNameLoc)
- : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
+ SourceLocation TemplateNameLoc,
+ SourceLocation EllipsisLoc = SourceLocation())
+ : Argument(Argument),
+ LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) {
assert(Argument.getKind() == TemplateArgument::Template);
}
return LocInfo.getTemplateNameLoc();
}
+ SourceLocation getTemplateEllipsisLoc() const {
+ assert(Argument.getKind() == TemplateArgument::Template);
+ return LocInfo.getTemplateEllipsisLoc();
+ }
+
/// \brief When the template argument is a pack expansion, returns
/// the pattern of the pack expansion.
///
SourceLocation TemplateLoc)
: Kind(ParsedTemplateArgument::Template),
Arg(Template.getAsOpaquePtr()),
- Loc(TemplateLoc), SS(SS) { }
+ Loc(TemplateLoc), SS(SS), EllipsisLoc() { }
/// \brief Determine whether the given template argument is invalid.
bool isInvalid() const { return Arg == 0; }
return SS;
}
+ /// \brief Retrieve the location of the ellipsis that makes a template
+ /// template argument into a pack expansion.
+ SourceLocation getEllipsisLoc() const {
+ assert(Kind == Template &&
+ "Only template template arguments can have an ellipsis");
+ return EllipsisLoc;
+ }
+
+ /// \brief Retrieve a pack expansion of the given template template
+ /// argument.
+ ///
+ /// \param EllipsisLoc The location of the ellipsis.
+ ParsedTemplateArgument getTemplatePackExpansion(
+ SourceLocation EllipsisLoc) const;
+
private:
KindType Kind;
/// \brief The nested-name-specifier that can accompany a template template
/// argument.
CXXScopeSpec SS;
+
+ /// \brief The ellipsis location that can accompany a template template
+ /// argument (turning it into a template template argument expansion).
+ SourceLocation EllipsisLoc;
};
/// \brief Information about a template-id annotation
Arg = TemplateArgument(E);
} else {
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
- // FIXME: Variadic templates.
- Arg = TemplateArgument(TemplateName(TTP));
+ Arg = TemplateArgument(TemplateName(TTP), TTP->isParameterPack());
}
if ((*Param)->isTemplateParameterPack()) {
return isa<PackExpansionType>(getAsType());
case Template:
- // FIXME: Template template pack expansions.
- break;
+ return TemplateArg.PackExpansion;
case Expression:
return isa<PackExpansionExpr>(getAsExpr());
break;
case Template:
- if (getAsTemplate().containsUnexpandedParameterPack())
+ if (!TemplateArg.PackExpansion &&
+ getAsTemplate().containsUnexpandedParameterPack())
return true;
break;
break;
case Template:
+ ID.AddBoolean(TemplateArg.PackExpansion);
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(
getAsTemplate().getAsTemplateDecl())) {
ID.AddBoolean(true);
ID.AddInteger(TTP->getDepth());
ID.AddInteger(TTP->getPosition());
+ ID.AddBoolean(TTP->isParameterPack());
} else {
ID.AddBoolean(false);
ID.AddPointer(Context.getCanonicalTemplateName(getAsTemplate())
case Null:
case Type:
case Declaration:
- case Template:
case Expression:
return TypeOrValue == Other.TypeOrValue;
+ case Template:
+ return TemplateArg.Template == Other.TemplateArg.Template &&
+ TemplateArg.PackExpansion == Other.TemplateArg.PackExpansion;
+
case Integral:
return getIntegralType() == Other.getIntegralType() &&
*getAsIntegral() == *Other.getAsIntegral();
assert(isPackExpansion());
switch (getKind()) {
- case Type:
- return getAsType()->getAs<PackExpansionType>()->getPattern();
-
- case Expression:
- return cast<PackExpansionExpr>(getAsExpr())->getPattern();
-
- case Template:
- // FIXME: Variadic templates.
- llvm_unreachable("Template pack expansions unsupported");
-
- case Declaration:
- case Integral:
- case Pack:
- case Null:
- return TemplateArgument();
+ case Type:
+ return getAsType()->getAs<PackExpansionType>()->getPattern();
+
+ case Expression:
+ return cast<PackExpansionExpr>(getAsExpr())->getPattern();
+
+ case Template:
+ return TemplateArgument(getAsTemplate(), false);
+
+ case Declaration:
+ case Integral:
+ case Pack:
+ case Null:
+ return TemplateArgument();
}
return TemplateArgument();
case Template: {
getAsTemplate().print(Out, Policy);
+ if (TemplateArg.PackExpansion)
+ Out << "...";
break;
}
break;
}
- case Expression: {
- // FIXME: This is non-optimal, since we're regurgitating the
- // expression we were given.
+ case Expression:
getAsExpr()->printPretty(Out, 0, Policy);
break;
- }
case Pack:
Out << "<";
else
return SourceRange();
- case TemplateArgument::Template:
+ case TemplateArgument::Template: {
+ SourceLocation End = getTemplateNameLoc();
+ if (getTemplateEllipsisLoc().isValid())
+ End = getTemplateEllipsisLoc();
if (getTemplateQualifierRange().isValid())
- return SourceRange(getTemplateQualifierRange().getBegin(),
- getTemplateNameLoc());
- return SourceRange(getTemplateNameLoc());
-
+ return SourceRange(getTemplateQualifierRange().getBegin(), End);
+ return SourceRange(getTemplateNameLoc(), End);
+ }
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
}
case TemplateArgument::Template:
- // FIXME: Variadic templates.
- llvm_unreachable("Template pack expansions unsupported");
+ return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
+ getTemplateQualifierRange(),
+ getTemplateNameLoc());
case TemplateArgument::Declaration:
case TemplateArgument::Integral:
return DB << Arg.getAsIntegral()->toString(10);
case TemplateArgument::Template:
- return DB << Arg.getAsTemplate();
+ DB << Arg.getAsTemplate();
+ if (Arg.isPackExpansion())
+ DB << "...";
+ return DB;
case TemplateArgument::Expression: {
// This shouldn't actually ever happen, so it's okay that we're
return 0;
}
+ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion(
+ SourceLocation EllipsisLoc) const {
+ assert(Kind == Template &&
+ "Only template template arguments can be pack expansions here");
+ assert(getAsTemplate().get().containsUnexpandedParameterPack() &&
+ "Template template argument pack expansion without packs");
+ ParsedTemplateArgument Result(*this);
+ Result.EllipsisLoc = EllipsisLoc;
+ return Result;
+}
+
static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
const ParsedTemplateArgument &Arg) {
case ParsedTemplateArgument::Template: {
TemplateName Template = Arg.getAsTemplate().get();
- return TemplateArgumentLoc(TemplateArgument(Template),
+ return TemplateArgumentLoc(TemplateArgument(Template,
+ Arg.getEllipsisLoc().isValid()),
Arg.getScopeSpec().getRange(),
- Arg.getLocation());
+ Arg.getLocation(),
+ Arg.getEllipsisLoc());
}
}
case TemplateArgument::Declaration: {
Expr *E
- = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+ = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
.takeAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::Integral: {
Expr *E
- = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
+ = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
return TemplateArgumentLoc(TemplateArgument(E), E);
}
case TemplateArgument::Template:
- return TemplateArgumentLoc(Arg, SourceRange(), Loc);
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc,
+ Arg.isPackExpansion()? Loc : SourceLocation());
case TemplateArgument::Expression:
return TemplateArgumentLoc(Arg, Arg.getAsExpr());
return true;
}
+
+ /// \brief Suppress traversal of template argument pack expansions.
+ bool TraverseTemplateArgument(const TemplateArgument &Arg) {
+ if (Arg.isPackExpansion())
+ return true;
+
+ return inherited::TraverseTemplateArgument(Arg);
+ }
+
+ /// \brief Suppress traversal of template argument pack expansions.
+ bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc) {
+ if (ArgLoc.getArgument().isPackExpansion())
+ return true;
+
+ return inherited::TraverseTemplateArgumentLoc(ArgLoc);
+ }
};
}
}
case ParsedTemplateArgument::Template:
- Diag(EllipsisLoc, diag::err_pack_expansion_unsupported);
- return ParsedTemplateArgument();
+ if (!Arg.getAsTemplate().get().containsUnexpandedParameterPack()) {
+ SourceRange R(Arg.getLocation());
+ if (Arg.getScopeSpec().isValid())
+ R.setBegin(Arg.getScopeSpec().getBeginLoc());
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << R;
+ return ParsedTemplateArgument();
+ }
+
+ return Arg.getTemplatePackExpansion(EllipsisLoc);
}
llvm_unreachable("Unhandled template argument kind?");
return ParsedTemplateArgument();
case TemplateArgument::Template: {
SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
- return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc);
+ SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
+ return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
+ EllipsisLoc);
}
case TemplateArgument::Null:
case TemplateArgument::Integral:
QualType T = GetType(Record[Idx++]);
return TemplateArgument(Value, T);
}
- case TemplateArgument::Template:
- return TemplateArgument(ReadTemplateName(Record, Idx));
+ case TemplateArgument::Template: {
+ TemplateName Name = ReadTemplateName(Record, Idx);
+ bool IsPackExpansion = Record[Idx++];
+ return TemplateArgument(Name, IsPackExpansion);
+ }
case TemplateArgument::Expression:
return TemplateArgument(ReadExpr(F));
case TemplateArgument::Pack: {
case TemplateArgument::Template:
AddSourceRange(Arg.getTemplateQualifierRange(), Record);
AddSourceLocation(Arg.getTemplateNameLoc(), Record);
+ AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record);
break;
case TemplateArgument::Null:
case TemplateArgument::Integral:
break;
case TemplateArgument::Template:
AddTemplateName(Arg.getAsTemplate(), Record);
+ Record.push_back(Arg.isPackExpansion());
break;
case TemplateArgument::Expression:
AddStmt(Arg.getAsExpr());
template<int... Values> struct X1nt;
template<int ...Values, int V> struct X1nt<V, Values...> { };
-// FIXME: Need template template argument packs!
-// template<template<int> class... Meta> struct X1tt;
-// template<template<int> class... Meta, template<int> class M>
-// struct X1tt<M, Meta...> { };
+template<template<int> class... Meta> struct X1tt;
+template<template<int> class... Meta, template<int> class M>
+ struct X1tt<M, Meta...> { };
template<typename ...Types, typename T>
void f1t(X1t<T, Types...>);
template<int ...Values, int V>
void f1nt(X1nt<V, Values...>);
-// FIXME: Need template template argument packs!
-// template<template<int> class... Meta, template<int> class M>
-// void f1tt(X1tt<M, Meta...>);
+template<template<int> class... Meta, template<int> class M>
+void f1tt(X1tt<M, Meta...>);