diff options
-rw-r--r-- | include/clang/AST/TemplateBase.h | 47 | ||||
-rw-r--r-- | include/clang/Sema/ParsedTemplate.h | 21 | ||||
-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 | ||||
-rw-r--r-- | test/CXX/temp/temp.param/p11-0x.cpp | 12 |
10 files changed, 159 insertions, 61 deletions
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index c7cb2fbe8e..758926c957 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -77,6 +77,10 @@ private: TemplateArgument *Args; unsigned NumArgs; } Args; + struct { + void *Template; + bool PackExpansion; + } TemplateArg; }; public: @@ -104,14 +108,21 @@ 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. @@ -142,8 +153,9 @@ public: } 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; } @@ -169,6 +181,8 @@ public: } 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; } @@ -220,8 +234,7 @@ public: 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. @@ -307,6 +320,7 @@ private: struct { unsigned QualifierRange[2]; unsigned TemplateNameLoc; + unsigned EllipsisLoc; } Template; }; @@ -318,11 +332,13 @@ public: 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 { @@ -342,6 +358,10 @@ public: SourceLocation getTemplateNameLoc() const { return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); } + + SourceLocation getTemplateEllipsisLoc() const { + return SourceLocation::getFromRawEncoding(Template.EllipsisLoc); + } }; /// Location wrapper for a TemplateArgument. TemplateArgument is to @@ -370,8 +390,10 @@ public: 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); } @@ -419,6 +441,11 @@ public: 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. /// diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h index 6a60ab1294..5aa6f47425 100644 --- a/include/clang/Sema/ParsedTemplate.h +++ b/include/clang/Sema/ParsedTemplate.h @@ -58,7 +58,7 @@ namespace clang { 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; } @@ -95,6 +95,21 @@ namespace clang { 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; @@ -109,6 +124,10 @@ namespace clang { /// \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 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()); diff --git a/test/CXX/temp/temp.param/p11-0x.cpp b/test/CXX/temp/temp.param/p11-0x.cpp index 00f56ab86d..d31a1f05fe 100644 --- a/test/CXX/temp/temp.param/p11-0x.cpp +++ b/test/CXX/temp/temp.param/p11-0x.cpp @@ -34,10 +34,9 @@ template<typename ...Types, typename T> struct X1t<T, Types...> { }; 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...>); @@ -45,6 +44,5 @@ 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...>); |