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
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 8832447..ff084c3 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -478,14 +478,9 @@
}
}
-/// \brief Retrieve the depth and index of an unexpanded parameter pack.
+/// \brief Retrieve the depth and index of a template parameter.
static std::pair<unsigned, unsigned>
-getDepthAndIndex(UnexpandedParameterPack UPP) {
- if (const TemplateTypeParmType *TTP
- = UPP.first.dyn_cast<const TemplateTypeParmType *>())
- return std::make_pair(TTP->getDepth(), TTP->getIndex());
-
- NamedDecl *ND = UPP.first.get<NamedDecl *>();
+getDepthAndIndex(NamedDecl *ND) {
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ND))
return std::make_pair(TTP->getDepth(), TTP->getIndex());
@@ -496,6 +491,16 @@
return std::make_pair(TTP->getDepth(), TTP->getIndex());
}
+/// \brief Retrieve the depth and index of an unexpanded parameter pack.
+static std::pair<unsigned, unsigned>
+getDepthAndIndex(UnexpandedParameterPack UPP) {
+ if (const TemplateTypeParmType *TTP
+ = UPP.first.dyn_cast<const TemplateTypeParmType *>())
+ return std::make_pair(TTP->getDepth(), TTP->getIndex());
+
+ return getDepthAndIndex(UPP.first.get<NamedDecl *>());
+}
+
/// \brief Helper function to build a TemplateParameter when we don't
/// know its type statically.
static TemplateParameter makeTemplateParameter(Decl *D) {
@@ -602,6 +607,12 @@
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+ // Keep track of the deduced template arguments for each parameter pack
+ // expanded by this pack expansion (the outer index) and for each
+ // template argument (the inner SmallVectors).
+ llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+ NewlyDeducedPacks(PackIndices.size());
+
// Save the deduced template arguments for each parameter pack expanded
// by this pack expansion, then clear out the deduction.
llvm::SmallVector<DeducedTemplateArgument, 2>
@@ -609,13 +620,21 @@
for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
SavedPacks[I] = Deduced[PackIndices[I]];
Deduced[PackIndices[I]] = DeducedTemplateArgument();
+
+ // If the template arugment pack was explicitly specified, add that to
+ // the set of deduced arguments.
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (NamedDecl *PartiallySubstitutedPack
+ = S.CurrentInstantiationScope->getPartiallySubstitutedPack(
+ &ExplicitArgs,
+ &NumExplicitArgs)) {
+ if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
+ NewlyDeducedPacks[I].append(ExplicitArgs,
+ ExplicitArgs + NumExplicitArgs);
+ }
}
- // Keep track of the deduced template arguments for each parameter pack
- // expanded by this pack expansion (the outer index) and for each
- // template argument (the inner SmallVectors).
- llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
bool HasAnyArguments = false;
for (; ArgIdx < NumArgs; ++ArgIdx) {
HasAnyArguments = true;
@@ -1879,13 +1898,30 @@
TemplateArgumentList *ExplicitArgumentList
= TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size());
Info.reset(ExplicitArgumentList);
-
+
// Template argument deduction and the final substitution should be
// done in the context of the templated declaration. Explicit
// argument substitution, on the other hand, needs to happen in the
// calling context.
ContextRAII SavedContext(*this, FunctionTemplate->getTemplatedDecl());
+ // If we deduced template arguments for a template parameter pack,
+ // note that the template argument pack is partially substituted and record
+ // the explicit template arguments. They'll be used as part of deduction
+ // for this template parameter pack.
+ bool HasPartiallySubstitutedPack = false;
+ for (unsigned I = 0, N = Builder.size(); I != N; ++I) {
+ const TemplateArgument &Arg = Builder[I];
+ if (Arg.getKind() == TemplateArgument::Pack) {
+ HasPartiallySubstitutedPack = true;
+ CurrentInstantiationScope->SetPartiallySubstitutedPack(
+ TemplateParams->getParam(I),
+ Arg.pack_begin(),
+ Arg.pack_size());
+ break;
+ }
+ }
+
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments.
if (SubstParmTypes(Function->getLocation(),
@@ -1927,11 +1963,18 @@
// template arguments can be deduced, they may all be omitted; in this
// case, the empty template argument list <> itself may also be omitted.
//
- // Take all of the explicitly-specified arguments and put them into the
- // set of deduced template arguments.
+ // Take all of the explicitly-specified arguments and put them into
+ // the set of deduced template arguments. Explicitly-specified
+ // parameter packs, however, will be set to NULL since the deduction
+ // mechanisms handle explicitly-specified argument packs directly.
Deduced.reserve(TemplateParams->size());
- for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I)
- Deduced.push_back(ExplicitArgumentList->get(I));
+ for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) {
+ const TemplateArgument &Arg = ExplicitArgumentList->get(I);
+ if (Arg.getKind() == TemplateArgument::Pack)
+ Deduced.push_back(DeducedTemplateArgument());
+ else
+ Deduced.push_back(Arg);
+ }
return TDK_Success;
}
@@ -2025,7 +2068,18 @@
// be deduced to an empty sequence of template arguments.
// FIXME: Where did the word "trailing" come from?
if (Param->isTemplateParameterPack()) {
- Builder.push_back(TemplateArgument(0, 0));
+ // We may have had explicitly-specified template arguments for this
+ // template parameter pack. If so, our empty deduction extends the
+ // explicitly-specified set (C++0x [temp.arg.explicit]p9).
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
+ &NumExplicitArgs)
+ == Param)
+ Builder.push_back(TemplateArgument(ExplicitArgs, NumExplicitArgs));
+ else
+ Builder.push_back(TemplateArgument(0, 0));
+
continue;
}
@@ -2446,20 +2500,36 @@
}
assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
- // Save the deduced template arguments for each parameter pack expanded
- // by this pack expansion, then clear out the deduction.
- llvm::SmallVector<DeducedTemplateArgument, 2>
- SavedPacks(PackIndices.size());
- for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
- SavedPacks[I] = Deduced[PackIndices[I]];
- Deduced[PackIndices[I]] = DeducedTemplateArgument();
- }
-
// Keep track of the deduced template arguments for each parameter pack
// expanded by this pack expansion (the outer index) and for each
// template argument (the inner SmallVectors).
llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
- NewlyDeducedPacks(PackIndices.size());
+ NewlyDeducedPacks(PackIndices.size());
+
+ // Save the deduced template arguments for each parameter pack expanded
+ // by this pack expansion, then clear out the deduction.
+ llvm::SmallVector<DeducedTemplateArgument, 2>
+ SavedPacks(PackIndices.size());
+ for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+ // Save the previously-deduced argument pack, then clear it out so that we
+ // can deduce a new argument pack.
+ SavedPacks[I] = Deduced[PackIndices[I]];
+ Deduced[PackIndices[I]] = TemplateArgument();
+
+ // If the template arugment pack was explicitly specified, add that to
+ // the set of deduced arguments.
+ const TemplateArgument *ExplicitArgs;
+ unsigned NumExplicitArgs;
+ if (NamedDecl *PartiallySubstitutedPack
+ = CurrentInstantiationScope->getPartiallySubstitutedPack(
+ &ExplicitArgs,
+ &NumExplicitArgs)) {
+ if (getDepthAndIndex(PartiallySubstitutedPack).second == PackIndices[I])
+ NewlyDeducedPacks[I].append(ExplicitArgs,
+ ExplicitArgs + NumExplicitArgs);
+ }
+ }
+
bool HasAnyArguments = false;
for (; ArgIdx < NumArgs; ++ArgIdx) {
HasAnyArguments = true;