]> granicus.if.org Git - clang/commitdiff
When mapping from a function parameter pack to the set of function
authorDouglas Gregor <dgregor@apple.com>
Tue, 11 Jan 2011 03:14:20 +0000 (03:14 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 11 Jan 2011 03:14:20 +0000 (03:14 +0000)
parameters it expanded to, map exactly the number of function
parameters that were expanded rather than just running to the end of
the instantiated parameter list. This finishes the implementation of
the last sentence of C++0x [temp.deduct.call]p1.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123213 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Sema/SemaTemplateVariadic.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p1-0x.cpp

index 368fe9dffaa9ac37e5616d61cbf9edfc0f187b65..d4ffd37bcae4825547db6b172cca4cc0b54a0825 100644 (file)
@@ -3383,6 +3383,15 @@ public:
                                        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.
   ///
index 50b24dc41d3280f7edcc771caf3ec8b9482bba09..a18bfbafc079522c4be85a4002dda927dc39457a 100644 (file)
@@ -1894,9 +1894,10 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
         // 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,
index 09e610c675cabd69690fa0c6be7fd123be30cd1f..63a8394d67a41794942ccf957a7a0b120a479c7b 100644 (file)
@@ -536,6 +536,50 @@ bool Sema::CheckParameterPacksForExpansion(SourceLocation EllipsisLoc,
   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()) {
index 4b480ddd3f1e6ccb29339b509b6990688ced7e3d..8933b63ee6df35219843edfe868111fe25079742 100644 (file)
@@ -78,8 +78,6 @@ void test_pair_deduction(int *ip, float *fp, double *dp) {
 // 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>
@@ -88,4 +86,3 @@ void pack_not_at_end(tuple<Types...>, Types... values, int);
 void test_pack_not_at_end(tuple<int*, double*> t2) {
   pack_not_at_end(t2, 0, 0, 0);
 }
-#endif