aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateVariadic.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-10 07:32:04 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-10 07:32:04 +0000
commitd3731198193eee92796ddeb493973b7a598b003e (patch)
tree2e177b315fbcbb6cbfbeb16e30171da0cc1e2e3f /lib/Sema/SemaTemplateVariadic.cpp
parent2770eb1294f425710e5802011e302a91a3614eb2 (diff)
Work-in-progress implementation of C++0x [temp.arg.explicit]p9, which
allows an argument pack determines via explicit specification of function template arguments to be extended by further, deduced arguments. For example: template<class ... Types> void f(Types ... values); void g() { f<int*, float*>(0, 0, 0); // Types is deduced to the sequence int*, float*, int } There are a number of FIXMEs in here that indicate places where we need to implement + test retained expansions, plus a number of other places in deduction where we need to correctly cope with the explicitly-specified arguments when deducing an argument pack. Furthermore, it appears that the RecursiveASTVisitor needs to be auditied; it's missing some traversals (especially w.r.t. template arguments) that cause it not to find unexpanded parameter packs when it should. The good news, however, is that the tr1::tuple implementation now works fully, and the tr1::bind example (both from N2080) is actually working now. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123163 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateVariadic.cpp')
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp45
1 files changed, 31 insertions, 14 deletions
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 1928c59642..09e610c675 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -419,14 +419,29 @@ ExprResult Sema::ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc) {
EllipsisLoc));
}
+/// \brief Retrieve the depth and index of a parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(NamedDecl *ND) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND))
+ return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+
+ TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(ND);
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
SourceRange PatternRange,
const UnexpandedParameterPack *Unexpanded,
unsigned NumUnexpanded,
const MultiLevelTemplateArgumentList &TemplateArgs,
bool &ShouldExpand,
+ bool &RetainExpansion,
unsigned &NumExpansions) {
ShouldExpand = true;
+ RetainExpansion = false;
std::pair<IdentifierInfo *, SourceLocation> FirstPack;
bool HaveFirstPack = false;
@@ -444,21 +459,11 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
Name = TTP->getName();
} else {
NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) {
- Depth = TTP->getDepth();
- Index = TTP->getIndex();
- } else if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(ND)) {
- Depth = NTTP->getDepth();
- Index = NTTP->getIndex();
- } else if (TemplateTemplateParmDecl *TTP
- = dyn_cast<TemplateTemplateParmDecl>(ND)) {
- Depth = TTP->getDepth();
- Index = TTP->getIndex();
- } else {
- assert(cast<ParmVarDecl>(ND)->isParameterPack());
+ if (isa<ParmVarDecl>(ND))
IsFunctionParameterPack = true;
- }
+ else
+ llvm::tie(Depth, Index) = getDepthAndIndex(ND);
+
Name = ND->getIdentifier();
}
@@ -495,6 +500,18 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
NewPackSize = TemplateArgs(Depth, Index).pack_size();
}
+ // C++0x [temp.arg.explicit]p9:
+ // Template argument deduction can extend the sequence of template
+ // arguments corresponding to a template parameter pack, even when the
+ // sequence contains explicitly specified template arguments.
+ if (NamedDecl *PartialPack
+ = CurrentInstantiationScope->getPartiallySubstitutedPack()) {
+ unsigned PartialDepth, PartialIndex;
+ llvm::tie(PartialDepth, PartialIndex) = getDepthAndIndex(PartialPack);
+ if (PartialDepth == Depth && PartialIndex == Index)
+ RetainExpansion = true;
+ }
+
if (!HaveFirstPack) {
// The is the first pack we've seen for which we have an argument.
// Record it.