bool &RetainExpansion,
unsigned &NumExpansions);
+ /// \brief Determine the number of arguments in the given pack expansion
+ /// type.
+ ///
+ /// This routine already assumes that the pack expansion type can be
+ /// expanded and that the number of arguments in the expansion is
+ /// consistent across all of the unexpanded parameter packs in its pattern.
+ unsigned getNumArgumentsInExpansion(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs);
+
/// \brief Determine whether the given declarator contains any unexpanded
/// parameter packs.
///
// Parameter pack: make the instantiation an argument pack.
SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(
OldParam);
- // FIXME: Variadic templates. Figure out how many arguments are in the
- // expansion of OldParam, so we don't gobble all of the arguments here.
- while (NewIdx < NumNewParams) {
+ unsigned NumArgumentsInExpansion
+ = SemaRef.getNumArgumentsInExpansion(OldParam->getType(),
+ TemplateArgs);
+ while (NumArgumentsInExpansion--) {
ParmVarDecl *NewParam = NewProtoLoc->getArg(NewIdx++);
Params.push_back(NewParam);
SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(OldParam,
return false;
}
+unsigned Sema::getNumArgumentsInExpansion(QualType T,
+ const MultiLevelTemplateArgumentList &TemplateArgs) {
+ QualType Pattern = cast<PackExpansionType>(T)->getPattern();
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(Pattern);
+
+ for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+ // Compute the depth and index for this parameter pack.
+ unsigned Depth;
+ unsigned Index;
+
+ if (const TemplateTypeParmType *TTP
+ = Unexpanded[I].first.dyn_cast<const TemplateTypeParmType *>()) {
+ Depth = TTP->getDepth();
+ Index = TTP->getIndex();
+ } else {
+ NamedDecl *ND = Unexpanded[I].first.get<NamedDecl *>();
+ if (isa<ParmVarDecl>(ND)) {
+ // Function parameter pack.
+ typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
+
+ llvm::PointerUnion<Decl *, DeclArgumentPack *> *Instantiation
+ = CurrentInstantiationScope->findInstantiationOf(
+ Unexpanded[I].first.get<NamedDecl *>());
+ if (Instantiation && Instantiation->is<DeclArgumentPack *>())
+ return Instantiation->get<DeclArgumentPack *>()->size();
+
+ continue;
+ }
+
+ llvm::tie(Depth, Index) = getDepthAndIndex(ND);
+ }
+ if (Depth >= TemplateArgs.getNumLevels() ||
+ !TemplateArgs.hasTemplateArgument(Depth, Index))
+ continue;
+
+ // Determine the size of the argument pack.
+ return TemplateArgs(Depth, Index).pack_size();
+ }
+
+ llvm_unreachable("No unexpanded parameter packs in type expansion.");
+ return 0;
+}
+
bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
const DeclSpec &DS = D.getDeclSpec();
switch (DS.getTypeSpecType()) {
// For a function parameter pack that does not occur at the end of the
// parameter-declaration-list, the type of the parameter pack is a
// non-deduced context.
-// FIXME: We're not in a position to handle this yet.
-#if 0
template<typename ...Types> struct tuple { };
template<typename ...Types>
void test_pack_not_at_end(tuple<int*, double*> t2) {
pack_not_at_end(t2, 0, 0, 0);
}
-#endif