return getDerived().TraverseType(Arg.getAsType());
case TemplateArgument::Template:
- return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(Arg.getAsExpr());
}
case TemplateArgument::Template:
- return getDerived().TraverseTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
case TemplateArgument::Expression:
return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
/// The template argument is a template name that was provided for a
/// template template parameter.
Template,
+ /// The template argument is a pack expansion of a template name that was
+ /// provided for a template template parameter.
+ TemplateExpansion,
/// The template argument is a value- or type-dependent expression
/// stored in an Expr*.
Expression,
TemplateArgument *Args;
unsigned NumArgs;
} Args;
- struct {
- void *Template;
- bool PackExpansion;
- } TemplateArg;
};
public:
/// \param Name The template name.
/// \param PackExpansion Whether this template argument is a pack expansion.
TemplateArgument(TemplateName Name, bool PackExpansion = false)
- : Kind(Template)
+ : Kind(PackExpansion? TemplateExpansion : Template)
{
- TemplateArg.Template = Name.getAsVoidPointer();
- TemplateArg.PackExpansion = PackExpansion;
+ TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
}
/// \brief Construct a template argument that is an expression.
} else if (Kind == Pack) {
Args.NumArgs = Other.Args.NumArgs;
Args.Args = Other.Args.Args;
- } 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(TemplateArg.Template);
+ return TemplateName::getFromVoidPointer(
+ reinterpret_cast<void*>(TypeOrValue));
}
-
+
+ /// \brief Retrieve the template argument as a template name; if the argument
+ /// is a pack expansion, return the pattern as a template name.
+ TemplateName getAsTemplateOrTemplatePattern() const {
+ if (Kind != Template && Kind != TemplateExpansion)
+ return TemplateName();
+
+ return TemplateName::getFromVoidPointer(
+ reinterpret_cast<void*>(TypeOrValue));
+ }
+
/// \brief Retrieve the template argument as an integral value.
llvm::APSInt *getAsIntegral() {
if (Kind != Integral)
SourceLocation EllipsisLoc = SourceLocation())
: Argument(Argument),
LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) {
- assert(Argument.getKind() == TemplateArgument::Template);
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
}
/// \brief - Fetches the primary location of the argument.
SourceLocation getLocation() const {
- if (Argument.getKind() == TemplateArgument::Template)
+ if (Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion)
return getTemplateNameLoc();
return getSourceRange().getBegin();
}
SourceRange getTemplateQualifierRange() const {
- assert(Argument.getKind() == TemplateArgument::Template);
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateQualifierRange();
}
SourceLocation getTemplateNameLoc() const {
- assert(Argument.getKind() == TemplateArgument::Template);
+ assert(Argument.getKind() == TemplateArgument::Template ||
+ Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateNameLoc();
}
SourceLocation getTemplateEllipsisLoc() const {
- assert(Argument.getKind() == TemplateArgument::Template);
+ assert(Argument.getKind() == TemplateArgument::TemplateExpansion);
return LocInfo.getTemplateEllipsisLoc();
}
case TemplateArgument::Template:
return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
-
+
+ case TemplateArgument::TemplateExpansion:
+ return TemplateArgument(getCanonicalTemplateName(
+ Arg.getAsTemplateOrTemplatePattern()),
+ true);
+
case TemplateArgument::Integral:
return TemplateArgument(*Arg.getAsIntegral(),
getCanonicalType(Arg.getIntegralType()));
return IsStructurallyEquivalent(Context,
Arg1.getAsTemplate(),
Arg2.getAsTemplate());
-
+
+ case TemplateArgument::TemplateExpansion:
+ return IsStructurallyEquivalent(Context,
+ Arg1.getAsTemplateOrTemplatePattern(),
+ Arg2.getAsTemplateOrTemplatePattern());
+
case TemplateArgument::Expression:
return IsStructurallyEquivalent(Context,
Arg1.getAsExpr(), Arg2.getAsExpr());
return TemplateArgument(ToTemplate);
}
-
+
+ case TemplateArgument::TemplateExpansion: {
+ TemplateName ToTemplate
+ = Importer.Import(From.getAsTemplateOrTemplatePattern());
+ if (ToTemplate.isNull())
+ return TemplateArgument();
+
+ return TemplateArgument(ToTemplate, true);
+ }
+
case TemplateArgument::Expression:
if (Expr *ToExpr = Importer.Import(From.getAsExpr()))
return TemplateArgument(ToExpr);
break;
case TemplateArgument::Template:
- if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
+ case TemplateArgument::TemplateExpansion:
+ if (TemplateDecl *Template
+ = Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl())
LV = merge(LV, getLVForDecl(Template, F));
break;
break;
}
case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ // FIXME: Implement!
+ break;
+
case TemplateArgument::Declaration: {
visitDeclRef(A.getAsDecl());
break;
break;
case TemplateArgument::Template:
- VisitTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
break;
case TemplateArgument::Declaration:
case Template:
return getAsTemplate().isDependent();
-
+
+ case TemplateExpansion:
+ return true;
+
case Declaration:
if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
return DC->isDependentContext();
case Declaration:
case Integral:
case Pack:
+ case Template:
return false;
+ case TemplateExpansion:
+ return true;
+
case Type:
return isa<PackExpansionType>(getAsType());
-
- case Template:
- return TemplateArg.PackExpansion;
-
+
case Expression:
return isa<PackExpansionExpr>(getAsExpr());
}
case Null:
case Declaration:
case Integral:
+ case TemplateExpansion:
break;
case Type:
break;
case Template:
- if (!TemplateArg.PackExpansion &&
- getAsTemplate().containsUnexpandedParameterPack())
+ if (getAsTemplate().containsUnexpandedParameterPack())
return true;
break;
break;
case Template:
- ID.AddBoolean(TemplateArg.PackExpansion);
+ case TemplateExpansion: {
+ TemplateName Template = getAsTemplateOrTemplatePattern();
if (TemplateTemplateParmDecl *TTP
= dyn_cast_or_null<TemplateTemplateParmDecl>(
- getAsTemplate().getAsTemplateDecl())) {
+ Template.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())
- .getAsVoidPointer());
+ ID.AddPointer(Context.getCanonicalTemplateName(Template)
+ .getAsVoidPointer());
}
break;
+ }
case Integral:
getAsIntegral()->Profile(ID);
case Null:
case Type:
case Declaration:
- case Expression:
+ case Expression:
+ case Template:
+ case TemplateExpansion:
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();
case Expression:
return cast<PackExpansionExpr>(getAsExpr())->getPattern();
- case Template:
- return TemplateArgument(getAsTemplate(), false);
+ case TemplateExpansion:
+ return TemplateArgument(getAsTemplateOrTemplatePattern(), false);
case Declaration:
case Integral:
case Pack:
case Null:
+ case Template:
return TemplateArgument();
}
break;
}
- case Template: {
+ case Template:
getAsTemplate().print(Out, Policy);
- if (TemplateArg.PackExpansion)
- Out << "...";
break;
- }
-
+
+ case TemplateExpansion:
+ getAsTemplateOrTemplatePattern().print(Out, Policy);
+ Out << "...";
+ break;
+
case Integral: {
Out << getAsIntegral()->toString(10);
break;
else
return SourceRange();
- case TemplateArgument::Template: {
- SourceLocation End = getTemplateNameLoc();
- if (getTemplateEllipsisLoc().isValid())
- End = getTemplateEllipsisLoc();
+ case TemplateArgument::Template:
if (getTemplateQualifierRange().isValid())
- return SourceRange(getTemplateQualifierRange().getBegin(), End);
- return SourceRange(getTemplateNameLoc(), End);
- }
-
+ return SourceRange(getTemplateQualifierRange().getBegin(),
+ getTemplateNameLoc());
+ return SourceRange(getTemplateNameLoc());
+
+ case TemplateArgument::TemplateExpansion:
+ if (getTemplateQualifierRange().isValid())
+ return SourceRange(getTemplateQualifierRange().getBegin(),
+ getTemplateEllipsisLoc());
+ return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
+
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
Expr *Pattern = cast<PackExpansionExpr>(Argument.getAsExpr())->getPattern();
return TemplateArgumentLoc(Pattern, Pattern);
}
-
- case TemplateArgument::Template:
+
+ case TemplateArgument::TemplateExpansion:
return TemplateArgumentLoc(Argument.getPackExpansionPattern(),
getTemplateQualifierRange(),
getTemplateNameLoc());
case TemplateArgument::Declaration:
+ case TemplateArgument::Template:
case TemplateArgument::Integral:
case TemplateArgument::Pack:
case TemplateArgument::Null:
return DB << Arg.getAsIntegral()->toString(10);
case TemplateArgument::Template:
- DB << Arg.getAsTemplate();
- if (Arg.isPackExpansion())
- DB << "...";
- return DB;
-
+ return DB << Arg.getAsTemplate();
+
+ case TemplateArgument::TemplateExpansion:
+ return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
+
case TemplateArgument::Expression: {
// This shouldn't actually ever happen, so it's okay that we're
// regurgitating an expression here.
// This is mangled as <type>.
mangleType(A.getAsTemplate());
break;
+ case TemplateArgument::TemplateExpansion:
+ // This is mangled as Dp <type>.
+ Out << "Dp";
+ mangleType(A.getAsTemplateOrTemplatePattern());
+ break;
case TemplateArgument::Expression:
Out << 'X';
mangleExpression(A.getAsExpr());
addAssociatedClassesAndNamespaces(Result, Arg.getAsType());
break;
- case TemplateArgument::Template: {
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
// [...] the namespaces in which any template template arguments are
// defined; and the classes in which any member templates used as
// template template arguments are defined.
- TemplateName Template = Arg.getAsTemplate();
+ TemplateName Template = Arg.getAsTemplateOrTemplatePattern();
if (ClassTemplateDecl *ClassTemplate
= dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
DeclContext *Ctx = ClassTemplate->getDeclContext();
break;
case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
// We were given a template template argument. It may not be ill-formed;
// see below.
if (DependentTemplateName *DTN
- = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+ = Arg.getArgument().getAsTemplateOrTemplatePattern()
+ .getAsDependentTemplateName()) {
// We have a template argument such as \c T::template X, which we
// parsed as a template template argument. However, since we now
// know that we need a non-type template argument, convert this
Arg.getTemplateQualifierRange(),
NameInfo);
+ // If we parsed the template argument as a pack expansion, create a
+ // pack expansion expression.
+ if (Arg.getArgument().getKind() == TemplateArgument::TemplateExpansion){
+ ExprResult Expansion = ActOnPackExpansion(E,
+ Arg.getTemplateEllipsisLoc());
+ if (Expansion.isInvalid())
+ return true;
+
+ E = Expansion.get();
+ }
+
TemplateArgument Result;
if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
return true;
return true;
case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
if (CheckTemplateArgument(TempParm, Arg))
return true;
// All other combinations are incompatible.
return DeducedTemplateArgument();
-
+
+ case TemplateArgument::TemplateExpansion:
+ if (Y.getKind() == TemplateArgument::TemplateExpansion &&
+ Context.hasSameTemplateName(X.getAsTemplateOrTemplatePattern(),
+ Y.getAsTemplateOrTemplatePattern()))
+ return X;
+
+ // All other combinations are incompatible.
+ return DeducedTemplateArgument();
+
case TemplateArgument::Expression:
// If we deduced a dependent expression in one case and either an integral
// constant or a declaration in another case, keep the integral constant
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
-
+
case TemplateArgument::Template:
if (Arg.getKind() == TemplateArgument::Template)
return DeduceTemplateArguments(S, TemplateParams,
Info.FirstArg = Param;
Info.SecondArg = Arg;
return Sema::TDK_NonDeducedMismatch;
+
+ case TemplateArgument::TemplateExpansion:
+ llvm_unreachable("caller should handle pack expansions");
+ break;
case TemplateArgument::Declaration:
if (Arg.getKind() == TemplateArgument::Declaration &&
Y.getAsDecl()->getCanonicalDecl();
case TemplateArgument::Template:
- return Context.getCanonicalTemplateName(X.getAsTemplate())
- .getAsVoidPointer() ==
- Context.getCanonicalTemplateName(Y.getAsTemplate())
- .getAsVoidPointer();
+ case TemplateArgument::TemplateExpansion:
+ return Context.getCanonicalTemplateName(
+ X.getAsTemplateOrTemplatePattern()).getAsVoidPointer() ==
+ Context.getCanonicalTemplateName(
+ Y.getAsTemplateOrTemplatePattern()).getAsVoidPointer();
case TemplateArgument::Integral:
return *X.getAsIntegral() == *Y.getAsIntegral();
}
case TemplateArgument::Template:
- return TemplateArgumentLoc(Arg, SourceRange(), Loc,
- Arg.isPackExpansion()? Loc : SourceLocation());
-
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc);
+
+ case TemplateArgument::TemplateExpansion:
+ return TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+
case TemplateArgument::Expression:
return TemplateArgumentLoc(Arg, Arg.getAsExpr());
break;
case TemplateArgument::Template:
- MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(),
+ case TemplateArgument::TemplateExpansion:
+ MarkUsedTemplateParameters(SemaRef,
+ TemplateArg.getAsTemplateOrTemplatePattern(),
OnlyDeduced, Depth, Used);
break;
}
case TemplateArgument::Template:
- llvm_unreachable("Unsupported pack expansion of templates");
+ return TemplateArgumentLoc(TemplateArgument(
+ Pattern.getArgument().getAsTemplate(),
+ true),
+ Pattern.getTemplateQualifierRange(),
+ Pattern.getTemplateNameLoc(),
+ EllipsisLoc);
case TemplateArgument::Null:
case TemplateArgument::Integral:
case TemplateArgument::Declaration:
case TemplateArgument::Pack:
+ case TemplateArgument::TemplateExpansion:
llvm_unreachable("Pack expansion pattern has no parameter packs");
case TemplateArgument::Type:
case TemplateArgument::Template:
Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
break;
-
+
+ case TemplateArgument::TemplateExpansion:
+ Output = TemplateArgumentLoc(Arg, SourceRange(), Loc, Loc);
+ break;
+
case TemplateArgument::Expression:
Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
break;
Input.getTemplateNameLoc());
return false;
}
-
+
+ case TemplateArgument::TemplateExpansion:
+ llvm_unreachable("Caller should expand pack expansions");
+
case TemplateArgument::Expression: {
// Template argument expressions are not potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(getSema(),
case TemplateArgument::Type:
return GetTypeSourceInfo(F, Record, Index);
case TemplateArgument::Template: {
+ SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
+ SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
+ return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc,
+ SourceLocation());
+ }
+ case TemplateArgument::TemplateExpansion: {
SourceRange QualifierRange = ReadSourceRange(F, Record, Index);
SourceLocation TemplateNameLoc = ReadSourceLocation(F, Record, Index);
SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Index);
TemplateArgument
ASTReader::ReadTemplateArgument(PerFileData &F,
const RecordData &Record, unsigned &Idx) {
- switch ((TemplateArgument::ArgKind)Record[Idx++]) {
+ TemplateArgument::ArgKind Kind = (TemplateArgument::ArgKind)Record[Idx++];
+ switch (Kind) {
case TemplateArgument::Null:
return TemplateArgument();
case TemplateArgument::Type:
QualType T = GetType(Record[Idx++]);
return TemplateArgument(Value, T);
}
- case TemplateArgument::Template: {
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion: {
TemplateName Name = ReadTemplateName(Record, Idx);
- bool IsPackExpansion = Record[Idx++];
- return TemplateArgument(Name, IsPackExpansion);
+ return TemplateArgument(Name, Kind == TemplateArgument::TemplateExpansion);
}
case TemplateArgument::Expression:
return TemplateArgument(ReadExpr(F));
AddTypeSourceInfo(Arg.getAsTypeSourceInfo(), Record);
break;
case TemplateArgument::Template:
+ AddSourceRange(Arg.getTemplateQualifierRange(), Record);
+ AddSourceLocation(Arg.getTemplateNameLoc(), Record);
+ break;
+ case TemplateArgument::TemplateExpansion:
AddSourceRange(Arg.getTemplateQualifierRange(), Record);
AddSourceLocation(Arg.getTemplateNameLoc(), Record);
AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record);
AddTypeRef(Arg.getIntegralType(), Record);
break;
case TemplateArgument::Template:
- AddTemplateName(Arg.getAsTemplate(), Record);
- Record.push_back(Arg.isPackExpansion());
+ case TemplateArgument::TemplateExpansion:
+ AddTemplateName(Arg.getAsTemplateOrTemplatePattern(), Record);
break;
case TemplateArgument::Expression:
AddStmt(Arg.getAsExpr());
int check0[is_same<apply_each<int,
add_reference, add_pointer, add_const>::type,
tuple<int&, int*, int const>>::value? 1 : -1];
+
+ template<typename T, template<class> class ...Meta>
+ struct apply_each_indirect {
+ typedef typename apply_each<T, Meta...>::type type;
+ };
+
+ int check1[is_same<apply_each_indirect<int, add_reference, add_pointer,
+ add_const>::type,
+ tuple<int&, int*, int const>>::value? 1 : -1];
+
+ template<typename T, typename ...Meta>
+ struct apply_each_nested {
+ typedef typename apply_each<T, Meta::template apply...>::type type;
+ };
+
+ struct add_reference_meta {
+ template<typename T>
+ struct apply {
+ typedef T& type;
+ };
+ };
+
+ struct add_pointer_meta {
+ template<typename T>
+ struct apply {
+ typedef T* type;
+ };
+ };
+
+ struct add_const_meta {
+ template<typename T>
+ struct apply {
+ typedef const T type;
+ };
+ };
+
+ int check2[is_same<apply_each_nested<int, add_reference_meta,
+ add_pointer_meta, add_const_meta>::type,
+ tuple<int&, int*, int const>>::value? 1 : -1];
+
}
static const bool value = true;
};
-// FIXME: Many more bullets to go
+// FIXME: Several more bullets to go
// In an initializer-list (8.5); the pattern is an initializer-clause.
// Note: this also covers expression-lists, since expression-list is
return false;
case TemplateArgument::Template:
- return VisitTemplateName(TAL.getArgument().getAsTemplate(),
+ case TemplateArgument::TemplateExpansion:
+ return VisitTemplateName(TAL.getArgument().getAsTemplateOrTemplatePattern(),
TAL.getTemplateNameLoc());
}
break;
case TemplateArgument::Template:
- VisitTemplateName(Arg.getAsTemplate());
+ case TemplateArgument::TemplateExpansion:
+ // FIXME: variadic templates
+ VisitTemplateName(Arg.getAsTemplateOrTemplatePattern());
break;
case TemplateArgument::Expression: