diff options
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()); |