diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-05 17:40:24 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-05 17:40:24 +0000 |
commit | ba68eca7582a62e3e2ff4b0eba1b2b73a6b80895 (patch) | |
tree | cda084548462f9d6bd3fdfe67d210f170baa0f04 /lib | |
parent | ec5e696a7523db8eae450f4593a80a27f32e530b (diff) |
Add semantic analysis for the creation of and an AST representation
for template template argument pack expansions. This allows fun such
as:
template<template<class> class ...> struct apply_impl { /*...*/ };
template<template<class> class ...Metafunctions> struct apply {
typedef typename apply_impl<Metafunctions...>::type type;
};
However, neither template argument deduction nor template
instantiation is implemented for template template argument packs, so
this functionality isn't useful yet.
I'll probably replace the encoding of template template
argument pack expansions in TemplateArgument so that it's harder to
accidentally forget about the expansion. However, this is a step in
the right general direction.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122890 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 3 | ||||
-rw-r--r-- | lib/AST/TemplateBase.cpp | 72 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 28 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 11 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 2 |
7 files changed, 97 insertions, 43 deletions
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 2755a9e230..b7a586cb17 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -335,8 +335,7 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() { 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()) { diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index c971519961..6eae6a4192 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -76,8 +76,7 @@ bool TemplateArgument::isPackExpansion() const { return isa<PackExpansionType>(getAsType()); case Template: - // FIXME: Template template pack expansions. - break; + return TemplateArg.PackExpansion; case Expression: return isa<PackExpansionExpr>(getAsExpr()); @@ -99,7 +98,8 @@ bool TemplateArgument::containsUnexpandedParameterPack() const { break; case Template: - if (getAsTemplate().containsUnexpandedParameterPack()) + if (!TemplateArg.PackExpansion && + getAsTemplate().containsUnexpandedParameterPack()) return true; break; @@ -135,12 +135,14 @@ void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID, 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()) @@ -171,10 +173,13 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 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(); @@ -195,21 +200,20 @@ TemplateArgument TemplateArgument::getPackExpansionPattern() const { 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(); @@ -246,6 +250,8 @@ void TemplateArgument::print(const PrintingPolicy &Policy, case Template: { getAsTemplate().print(Out, Policy); + if (TemplateArg.PackExpansion) + Out << "..."; break; } @@ -254,12 +260,9 @@ void TemplateArgument::print(const PrintingPolicy &Policy, 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 << "<"; @@ -296,12 +299,15 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { 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: @@ -351,8 +357,9 @@ TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, } case TemplateArgument::Template: - // FIXME: Variadic templates. - llvm_unreachable("Template pack expansions unsupported"); + return TemplateArgumentLoc(Argument.getPackExpansionPattern(), + getTemplateQualifierRange(), + getTemplateNameLoc()); case TemplateArgument::Declaration: case TemplateArgument::Integral: @@ -382,7 +389,10 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 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 diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ff0fe9d6b6..9adcf1c81f 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -437,6 +437,17 @@ TemplateDecl *Sema::AdjustDeclIfTemplate(Decl *&D) { 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) { @@ -456,9 +467,11 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, 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()); } } diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 18bfee301b..a72a29378a 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -1344,19 +1344,20 @@ getTrivialTemplateArgumentLoc(Sema &S, 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()); diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index acb73144d9..fb88bd114b 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -130,6 +130,22 @@ namespace { 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); + } }; } @@ -335,8 +351,16 @@ Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg, } 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(); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index f3320a0415..ed0e58f18f 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3381,7 +3381,9 @@ ASTReader::GetTemplateArgumentLocInfo(PerFileData &F, 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: @@ -4226,8 +4228,11 @@ ASTReader::ReadTemplateArgument(PerFileData &F, 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: { diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index cbf5ac7919..44f17e40b1 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -2889,6 +2889,7 @@ void ASTWriter::AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, case TemplateArgument::Template: AddSourceRange(Arg.getTemplateQualifierRange(), Record); AddSourceLocation(Arg.getTemplateNameLoc(), Record); + AddSourceLocation(Arg.getTemplateEllipsisLoc(), Record); break; case TemplateArgument::Null: case TemplateArgument::Integral: @@ -3176,6 +3177,7 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg, break; case TemplateArgument::Template: AddTemplateName(Arg.getAsTemplate(), Record); + Record.push_back(Arg.isPackExpansion()); break; case TemplateArgument::Expression: AddStmt(Arg.getAsExpr()); |