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/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 2c9a430..f540c7b 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2550,10 +2550,13 @@
   
   // Form argument packs for each of the parameter packs remaining.
   while (Param != ParamEnd) {
+    // If we're checking a partial list of template arguments, don't fill
+    // in arguments for non-template parameter packs.
+    
     if ((*Param)->isTemplateParameterPack()) {     
-      // The parameter pack takes the contents of the current argument pack,
-      // which we built up earlier.
-      if (ArgumentPack.empty()) {
+      if (PartialTemplateArgs && ArgumentPack.empty()) {
+        Converted.push_back(TemplateArgument());
+      } else if (ArgumentPack.empty()) {
         Converted.push_back(TemplateArgument(0, 0));
       } else {
         TemplateArgument *PackedArgs
@@ -3600,7 +3603,7 @@
 Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg,
                                                   SourceLocation Loc) {
   assert(Arg.getKind() == TemplateArgument::Integral &&
-         "Operation is only value for integral template arguments");
+         "Operation is only valid for integral template arguments");
   QualType T = Arg.getIntegralType();
   if (T->isCharType() || T->isWideCharType())
     return Owned(new (Context) CharacterLiteral(
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;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 394f50e..5f181fb 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -564,6 +564,19 @@
   return 0;
 }
 
+/// \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());
+}
+
 //===----------------------------------------------------------------------===/
 // Template Instantiation for Types
 //===----------------------------------------------------------------------===/
@@ -608,12 +621,14 @@
                                  const UnexpandedParameterPack *Unexpanded,
                                  unsigned NumUnexpanded,
                                  bool &ShouldExpand,
+                                 bool &RetainExpansion,
                                  unsigned &NumExpansions) {
       return getSema().CheckParameterPacksForExpansion(EllipsisLoc, 
                                                        PatternRange, Unexpanded,
                                                        NumUnexpanded, 
                                                        TemplateArgs, 
                                                        ShouldExpand,
+                                                       RetainExpansion,
                                                        NumExpansions);
     }
 
@@ -621,6 +636,37 @@
       SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Pack);
     }
     
+    TemplateArgument ForgetPartiallySubstitutedPack() {
+      TemplateArgument Result;
+      if (NamedDecl *PartialPack
+            = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
+        MultiLevelTemplateArgumentList &TemplateArgs
+          = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+        unsigned Depth, Index;
+        llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+        if (TemplateArgs.hasTemplateArgument(Depth, Index)) {
+          Result = TemplateArgs(Depth, Index);
+          TemplateArgs.setArgument(Depth, Index, TemplateArgument());
+        }
+      }
+      
+      return Result;
+    }
+    
+    void RememberPartiallySubstitutedPack(TemplateArgument Arg) {
+      if (Arg.isNull())
+        return;
+      
+      if (NamedDecl *PartialPack
+            = SemaRef.CurrentInstantiationScope->getPartiallySubstitutedPack()){
+        MultiLevelTemplateArgumentList &TemplateArgs
+        = const_cast<MultiLevelTemplateArgumentList &>(this->TemplateArgs);
+        unsigned Depth, Index;
+        llvm::tie(Depth, Index) = getDepthAndIndex(PartialPack);
+        TemplateArgs.setArgument(Depth, Index, Arg);
+      }
+    }
+
     /// \brief Transform the given declaration by instantiating a reference to
     /// this declaration.
     Decl *TransformDecl(SourceLocation Loc, Decl *D);
@@ -713,6 +759,7 @@
           return 0;
         }
         
+        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
         Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
       }
 
@@ -761,6 +808,7 @@
           return 0;
         }
         
+        assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
         Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
       }
 
@@ -877,6 +925,7 @@
       return ExprError();
     }
     
+    assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
     Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
   }
 
@@ -981,6 +1030,7 @@
         return QualType();
       }
       
+      assert(getSema().ArgumentPackSubstitutionIndex < (int)Arg.pack_size());
       Arg = Arg.pack_begin()[getSema().ArgumentPackSubstitutionIndex];
     }
     
@@ -1272,11 +1322,13 @@
       collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(),
                                       Unexpanded);
       bool ShouldExpand = false;
+      bool RetainExpansion = false;
       unsigned NumExpansions = 0;
       if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(), 
                                           Base->getSourceRange(),
                                           Unexpanded.data(), Unexpanded.size(),
                                           TemplateArgs, ShouldExpand, 
+                                          RetainExpansion,
                                           NumExpansions)) {
         Invalid = true;
         continue;
@@ -1959,9 +2011,13 @@
 
 void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
   llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
-  assert((Stored.isNull() || 
-          (Stored.get<Decl *>() == Inst)) && "Already instantiated this local");
-  Stored = Inst;
+  if (Stored.isNull())
+    Stored = Inst;
+  else if (Stored.is<Decl *>()) {
+    assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
+    Stored = Inst;
+  } else
+    LocalDecls[D].get<DeclArgumentPack *>()->push_back(Inst);
 }
 
 void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D, 
@@ -1978,3 +2034,41 @@
   ArgumentPacks.push_back(Pack);
 }
 
+void LocalInstantiationScope::SetPartiallySubstitutedPack(NamedDecl *Pack, 
+                                          const TemplateArgument *ExplicitArgs,
+                                                    unsigned NumExplicitArgs) {
+  assert((!PartiallySubstitutedPack || PartiallySubstitutedPack == Pack) &&
+         "Already have a partially-substituted pack");
+  assert((!PartiallySubstitutedPack 
+          || NumArgsInPartiallySubstitutedPack == NumExplicitArgs) &&
+         "Wrong number of arguments in partially-substituted pack");
+  PartiallySubstitutedPack = Pack;
+  ArgsInPartiallySubstitutedPack = ExplicitArgs;
+  NumArgsInPartiallySubstitutedPack = NumExplicitArgs;
+}
+
+NamedDecl *LocalInstantiationScope::getPartiallySubstitutedPack(
+                                         const TemplateArgument **ExplicitArgs,
+                                              unsigned *NumExplicitArgs) const {
+  if (ExplicitArgs)
+    *ExplicitArgs = 0;
+  if (NumExplicitArgs)
+    *NumExplicitArgs = 0;
+  
+  for (const LocalInstantiationScope *Current = this; Current; 
+       Current = Current->Outer) {
+    if (Current->PartiallySubstitutedPack) {
+      if (ExplicitArgs)
+        *ExplicitArgs = Current->ArgsInPartiallySubstitutedPack;
+      if (NumExplicitArgs)
+        *NumExplicitArgs = Current->NumArgsInPartiallySubstitutedPack;
+      
+      return Current->PartiallySubstitutedPack;
+    }
+
+    if (!Current->CombineWithOuterScope)
+      break;
+  }
+  
+  return 0;
+}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e59f94a..c29ff86 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1973,13 +1973,16 @@
                "Pack expansion without parameter packs?");
         
         bool Expand = false;
+        bool RetainExpansion = false;
         unsigned NumExpansions = 0;
         if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(), 
                                                     SourceRange(),
                                                     Unexpanded.data(), 
                                                     Unexpanded.size(),
                                                     TemplateArgs,
-                                                    Expand, NumExpansions))
+                                                    Expand, 
+                                                    RetainExpansion,
+                                                    NumExpansions))
           break;
                       
         if (!Expand) {
@@ -2377,12 +2380,14 @@
       llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
       collectUnexpandedParameterPacks(BaseTL, Unexpanded);
       bool ShouldExpand = false;
+      bool RetainExpansion = false;
       unsigned NumExpansions = 0;
       if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), 
                                           BaseTL.getSourceRange(),
                                           Unexpanded.data(), 
                                           Unexpanded.size(),
                                           TemplateArgs, ShouldExpand, 
+                                          RetainExpansion,
                                           NumExpansions)) {
         AnyErrors = true;
         New->setInvalidDecl();
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index 1928c59..09e610c 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -419,14 +419,29 @@
                                                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 @@
       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 @@
       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.
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index e2bfb05..7eee444 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -89,6 +89,23 @@
 /// (\c getBaseLocation(), \c getBaseEntity()).
 template<typename Derived>
 class TreeTransform {
+  /// \brief Private RAII object that helps us forget and then re-remember
+  /// the template argument corresponding to a partially-substituted parameter
+  /// pack.
+  class ForgetPartiallySubstitutedPackRAII {
+    Derived &Self;
+    TemplateArgument Old;
+    
+  public:
+    ForgetPartiallySubstitutedPackRAII(Derived &Self) : Self(Self) {
+      Old = Self.ForgetPartiallySubstitutedPack();
+    }
+    
+    ~ForgetPartiallySubstitutedPackRAII() {
+      Self.RememberPartiallySubstitutedPack(Old);
+    }
+  };
+  
 protected:
   Sema &SemaRef;
   
@@ -204,6 +221,11 @@
   /// expand the corresponding pack expansions into separate arguments. When
   /// set, \c NumExpansions must also be set.
   ///
+  /// \param RetainExpansion Whether the caller should add an unexpanded
+  /// pack expansion after all of the expanded arguments. This is used
+  /// when extending explicitly-specified template argument packs per
+  /// C++0x [temp.arg.explicit]p9.
+  ///
   /// \param NumExpansions The number of separate arguments that will be in
   /// the expanded form of the corresponding pack expansion. Must be set when
   /// \c ShouldExpand is \c true.
@@ -217,11 +239,28 @@
                                const UnexpandedParameterPack *Unexpanded,
                                unsigned NumUnexpanded,
                                bool &ShouldExpand,
+                               bool &RetainExpansion,
                                unsigned &NumExpansions) {
     ShouldExpand = false;
     return false;
   }
   
+  /// \brief "Forget" about the partially-substituted pack template argument,
+  /// when performing an instantiation that must preserve the parameter pack
+  /// use.
+  ///
+  /// This routine is meant to be overridden by the template instantiator.
+  TemplateArgument ForgetPartiallySubstitutedPack() {
+    return TemplateArgument();
+  }
+  
+  /// \brief "Remember" the partially-substituted pack template argument
+  /// after performing an instantiation that must preserve the parameter pack
+  /// use.
+  ///
+  /// This routine is meant to be overridden by the template instantiator.
+  void RememberPartiallySubstitutedPack(TemplateArgument Arg) { }
+  
   /// \brief Note to the derived class when a function parameter pack is
   /// being expanded.
   void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { }
@@ -2250,12 +2289,14 @@
       // Determine whether the set of unexpanded parameter packs can and should
       // be expanded.
       bool Expand = true;
+      bool RetainExpansion = false;
       unsigned NumExpansions = 0;
       if (getDerived().TryExpandParameterPacks(Expansion->getEllipsisLoc(),
                                                Pattern->getSourceRange(),
                                                Unexpanded.data(),
                                                Unexpanded.size(),
-                                               Expand, NumExpansions))
+                                               Expand, RetainExpansion,
+                                               NumExpansions))
         return true;
         
       if (!Expand) {
@@ -2770,12 +2811,15 @@
       // Determine whether the set of unexpanded parameter packs can and should
       // be expanded.
       bool Expand = true;
+      bool RetainExpansion = false;
       unsigned NumExpansions = 0;
       if (getDerived().TryExpandParameterPacks(Ellipsis,
                                                Pattern.getSourceRange(),
                                                Unexpanded.data(),
                                                Unexpanded.size(),
-                                               Expand, NumExpansions))
+                                               Expand, 
+                                               RetainExpansion,
+                                               NumExpansions))
         return true;
       
       if (!Expand) {
@@ -2806,6 +2850,8 @@
         Outputs.addArgument(Out);
       }
       
+      // FIXME: Variadic templates retain expansion!
+      
       continue;
     }
     
@@ -3415,12 +3461,15 @@
         
         // Determine whether we should expand the parameter packs.
         bool ShouldExpand = false;
+        bool RetainExpansion = false;
         unsigned NumExpansions = 0;
         if (getDerived().TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(),
                                                  Pattern.getSourceRange(),
                                                  Unexpanded.data(), 
                                                  Unexpanded.size(),
-                                                 ShouldExpand, NumExpansions)) {
+                                                 ShouldExpand, 
+                                                 RetainExpansion,
+                                                 NumExpansions)) {
           return true;
         }
         
@@ -3439,7 +3488,21 @@
             if (PVars)
               PVars->push_back(NewParm);
           }
-          
+
+          // If we're supposed to retain a pack expansion, do so by temporarily
+          // forgetting the partially-substituted parameter pack.
+          if (RetainExpansion) {
+            ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+            ParmVarDecl *NewParm 
+              = getDerived().TransformFunctionTypeParam(OldParm);
+            if (!NewParm)
+              return true;
+            
+            OutParamTypes.push_back(NewParm->getType());
+            if (PVars)
+              PVars->push_back(NewParm);
+          }
+
           // We're done with the pack expansion.
           continue;
         }
@@ -3472,11 +3535,14 @@
       
       // Determine whether we should expand the parameter packs.
       bool ShouldExpand = false;
+      bool RetainExpansion = false;
       unsigned NumExpansions = 0;
       if (getDerived().TryExpandParameterPacks(Loc, SourceRange(),
                                                Unexpanded.data(), 
                                                Unexpanded.size(),
-                                               ShouldExpand, NumExpansions)) {
+                                               ShouldExpand, 
+                                               RetainExpansion,
+                                               NumExpansions)) {
         return true;
       }
       
@@ -3498,6 +3564,8 @@
         continue;
       }
       
+      // FIXME: Variadic templates retain pack expansion!
+
       // We'll substitute the parameter now without expanding the pack 
       // expansion.
       OldType = Expansion->getPattern();
@@ -6674,13 +6742,15 @@
   // so 
   UnexpandedParameterPack Unexpanded(E->getPack(), E->getPackLoc());
   bool ShouldExpand = false;
+  bool RetainExpansion = false;
   unsigned NumExpansions = 0;
   if (getDerived().TryExpandParameterPacks(E->getOperatorLoc(), E->getPackLoc(), 
                                            &Unexpanded, 1, 
-                                           ShouldExpand, NumExpansions))
+                                           ShouldExpand, RetainExpansion,
+                                           NumExpansions))
     return ExprError();
   
-  if (!ShouldExpand)
+  if (!ShouldExpand || RetainExpansion)
     return SemaRef.Owned(E);
   
   // We now know the length of the parameter pack, so build a new expression