summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/TemplateBase.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-05 17:40:24 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-05 17:40:24 +0000
commiteb29d18e5da3452d57891135dcfadd5e8eac5102 (patch)
treea9b9cddde3be8bd7f545843354d43a53e74ab002 /clang/lib/AST/TemplateBase.cpp
parent07fd1efcfa6ac0b5f2abfb25df29b002180ab380 (diff)
downloadbcm5719-llvm-eb29d18e5da3452d57891135dcfadd5e8eac5102.tar.gz
bcm5719-llvm-eb29d18e5da3452d57891135dcfadd5e8eac5102.zip
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. llvm-svn: 122890
Diffstat (limited to 'clang/lib/AST/TemplateBase.cpp')
-rw-r--r--clang/lib/AST/TemplateBase.cpp72
1 files changed, 41 insertions, 31 deletions
diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index c9715199612..6eae6a4192f 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/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
OpenPOWER on IntegriCloud