aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/DeclTemplate.cpp3
-rw-r--r--lib/AST/TemplateBase.cpp72
-rw-r--r--lib/Sema/SemaTemplate.cpp17
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp7
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp28
-rw-r--r--lib/Serialization/ASTReader.cpp11
-rw-r--r--lib/Serialization/ASTWriter.cpp2
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());