diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-12-20 22:05:00 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-12-20 22:05:00 +0000 |
commit | 8491ffe86c50241b47c6d7ef8cd9ee00f5e675da (patch) | |
tree | 4e3c218dcecedab5e67490889c410120cd6ef52a /lib/AST/TemplateBase.cpp | |
parent | 342e907d72c1644ca294115dabd5ed8e852bc4ed (diff) |
Implement basic support for template instantiation of pack expansions
whose patterns are template arguments. We can now instantiate, e.g.,
typedef tuple<pair<OuterTypes, InnerTypes>...> type;
where OuterTypes and InnerTypes are template type parameter packs.
There is a horrible inefficiency in
TemplateArgumentLoc::getPackExpansionPattern(), where we need to
create copies of TypeLoc data because our interfaces traffic in
TypeSourceInfo pointers where they should traffic in TypeLocs
instead. I've isolated in efficiency in this one routine; once we
refactor our interfaces to traffic in TypeLocs, we can eliminate it.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122278 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/TemplateBase.cpp')
-rw-r--r-- | lib/AST/TemplateBase.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp index ee40485226..fd1146c084 100644 --- a/lib/AST/TemplateBase.cpp +++ b/lib/AST/TemplateBase.cpp @@ -63,6 +63,29 @@ bool TemplateArgument::isDependent() const { return false; } +bool TemplateArgument::isPackExpansion() const { + switch (getKind()) { + case Null: + case Declaration: + case Integral: + case Pack: + return false; + + case Type: + return llvm::isa<PackExpansionType>(getAsType()); + + case Template: + // FIXME: Template template pack expansions. + break; + + case Expression: + // FIXME: Expansion pack expansions. + break; + } + + return false; +} + bool TemplateArgument::containsUnexpandedParameterPack() const { switch (getKind()) { case Null: @@ -265,6 +288,47 @@ SourceRange TemplateArgumentLoc::getSourceRange() const { return SourceRange(); } +TemplateArgumentLoc +TemplateArgumentLoc::getPackExpansionPattern(SourceLocation &Ellipsis, + ASTContext &Context) const { + assert(Argument.isPackExpansion()); + + switch (Argument.getKind()) { + case TemplateArgument::Type: { + PackExpansionTypeLoc Expansion + = cast<PackExpansionTypeLoc>(getTypeSourceInfo()->getTypeLoc()); + Ellipsis = Expansion.getEllipsisLoc(); + + TypeLoc Pattern = Expansion.getPatternLoc(); + + // FIXME: This is horrible. We know where the source location data is for + // the pattern, and we have the pattern's type, but we are forced to copy + // them into an ASTContext because TypeSourceInfo bundles them together + // and TemplateArgumentLoc traffics in TypeSourceInfo pointers. + TypeSourceInfo *PatternTSInfo + = Context.CreateTypeSourceInfo(Pattern.getType(), + Pattern.getFullDataSize()); + memcpy(PatternTSInfo->getTypeLoc().getOpaqueData(), + Pattern.getOpaqueData(), Pattern.getFullDataSize()); + return TemplateArgumentLoc(TemplateArgument(Pattern.getType()), + PatternTSInfo); + } + + case TemplateArgument::Expression: + case TemplateArgument::Template: + // FIXME: Variadic templates. + llvm_unreachable("Expression and template pack expansions unsupported"); + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + case TemplateArgument::Pack: + case TemplateArgument::Null: + return TemplateArgumentLoc(); + } + + return TemplateArgumentLoc(); +} + const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, const TemplateArgument &Arg) { switch (Arg.getKind()) { |