PR32010: Fix template argument depth mixup when forming implicit constructor
template deduction guides for class template argument deduction.

Ensure that we have a local instantiation scope for tracking the instantiated
parameters. Additionally, unusually, we're substituting at depth 1 and leaving
depth 0 alone; make sure that we don't reduce template parameter depth by 2 for
inner parameters in the process. (This is probably also broken for alias
templates in the case where they're expanded within a dependent context, but
this patch doesn't fix that.)

llvm-svn: 295696
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index e83ec3c..2879452 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1479,6 +1479,7 @@
                                                       unsigned NumExpansions);
   
   using TemplateParmPosition::getDepth;
+  using TemplateParmPosition::setDepth;
   using TemplateParmPosition::getPosition;
   using TemplateParmPosition::setPosition;
   using TemplateParmPosition::getIndex;
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 401bbbf..644d55b 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -46,6 +46,10 @@
     /// \brief The template argument lists, stored from the innermost template
     /// argument list (first) to the outermost template argument list (last).
     SmallVector<ArgList, 4> TemplateArgumentLists;
+
+    /// \brief The number of outer levels of template arguments that are not
+    /// being substituted.
+    unsigned NumRetainedOuterLevels = 0;
     
   public:
     /// \brief Construct an empty set of template argument lists.
@@ -59,11 +63,19 @@
     
     /// \brief Determine the number of levels in this template argument
     /// list.
-    unsigned getNumLevels() const { return TemplateArgumentLists.size(); }
-    
+    unsigned getNumLevels() const {
+      return TemplateArgumentLists.size() + NumRetainedOuterLevels;
+    }
+
+    /// \brief Determine the number of substituted levels in this template
+    /// argument list.
+    unsigned getNumSubstitutedLevels() const {
+      return TemplateArgumentLists.size();
+    }
+
     /// \brief Retrieve the template argument at a given depth and index.
     const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
-      assert(Depth < TemplateArgumentLists.size());
+      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
       assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
       return TemplateArgumentLists[getNumLevels() - Depth - 1][Index];
     }
@@ -73,7 +85,10 @@
     ///
     /// There must exist a template argument list at the given depth.
     bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
-      assert(Depth < TemplateArgumentLists.size());
+      assert(Depth < getNumLevels());
+
+      if (Depth < NumRetainedOuterLevels)
+        return false;
       
       if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size())
         return false;
@@ -84,7 +99,7 @@
     /// \brief Clear out a specific template argument.
     void setArgument(unsigned Depth, unsigned Index,
                      TemplateArgument Arg) {
-      assert(Depth < TemplateArgumentLists.size());
+      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
       assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
       const_cast<TemplateArgument&>(
                 TemplateArgumentLists[getNumLevels() - Depth - 1][Index])
@@ -101,9 +116,18 @@
     /// \brief Add a new outmost level to the multi-level template argument
     /// list.
     void addOuterTemplateArguments(ArgList Args) {
+      assert(!NumRetainedOuterLevels &&
+             "substituted args outside retained args?");
       TemplateArgumentLists.push_back(Args);
     }
 
+    /// \brief Add an outermost level that we are not substituting. We have no
+    /// arguments at this level, and do not remove it from the depth of inner
+    /// template parameters that we instantiate.
+    void addOuterRetainedLevel() {
+      ++NumRetainedOuterLevels;
+    }
+
     /// \brief Retrieve the innermost template argument list.
     const ArgList &getInnermost() const { 
       return TemplateArgumentLists.front(); 
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 4b4a47d..ad7b9e5 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1442,6 +1442,8 @@
                                   CXXConstructorDecl *CD) {
     SmallVector<TemplateArgument, 16> SubstArgs;
 
+    LocalInstantiationScope Scope(SemaRef);
+
     // C++ [over.match.class.deduct]p1:
     // -- For each constructor of the class template designated by the
     //    template-name, a function template with the following properties:
@@ -1463,7 +1465,7 @@
       for (NamedDecl *Param : *InnerParams) {
         MultiLevelTemplateArgumentList Args;
         Args.addOuterTemplateArguments(SubstArgs);
-        Args.addOuterTemplateArguments(None);
+        Args.addOuterRetainedLevel();
         NamedDecl *NewParam = transformTemplateParameter(Param, Args);
         if (!NewParam)
           return nullptr;
@@ -1483,7 +1485,7 @@
     MultiLevelTemplateArgumentList Args;
     if (FTD) {
       Args.addOuterTemplateArguments(SubstArgs);
-      Args.addOuterTemplateArguments(None);
+      Args.addOuterRetainedLevel();
     }
 
     FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()->getTypeLoc()
@@ -1555,6 +1557,8 @@
         if (InstantiatedDefaultArg)
           NewTTP->setDefaultArgument(InstantiatedDefaultArg);
       }
+      SemaRef.CurrentInstantiationScope->InstantiatedLocal(TemplateParam,
+                                                           NewTTP);
       return NewTTP;
     }
 
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 723a6c0..f7535e6 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1121,6 +1121,23 @@
     return E;
 
   TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
+
+  if (TemplateArgs.getNumLevels() != TemplateArgs.getNumSubstitutedLevels()) {
+    // We're performing a partial substitution, so the substituted argument
+    // could be dependent. As a result we can't create a SubstNonType*Expr
+    // node now, since that represents a fully-substituted argument.
+    // FIXME: We should have some AST representation for this.
+    if (Arg.getKind() == TemplateArgument::Pack) {
+      // FIXME: This won't work for alias templates.
+      assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() &&
+             "unexpected pack arguments in partial substitution");
+      Arg = Arg.pack_begin()->getPackExpansionPattern();
+    }
+    assert(Arg.getKind() == TemplateArgument::Expression &&
+           "unexpected nontype template argument kind in partial substitution");
+    return Arg.getAsExpr();
+  }
+
   if (NTTP->isParameterPack()) {
     assert(Arg.getKind() == TemplateArgument::Pack && 
            "Missing argument pack");
@@ -1429,12 +1446,9 @@
     NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
                                   TransformDecl(TL.getNameLoc(), OldTTPDecl));
 
-  QualType Result
-    = getSema().Context.getTemplateTypeParmType(T->getDepth()
-                                                 - TemplateArgs.getNumLevels(),
-                                                T->getIndex(),
-                                                T->isParameterPack(),
-                                                NewTTPDecl);
+  QualType Result = getSema().Context.getTemplateTypeParmType(
+      T->getDepth() - TemplateArgs.getNumSubstitutedLevels(), T->getIndex(),
+      T->isParameterPack(), NewTTPDecl);
   TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
   NewTL.setNameLoc(TL.getNameLoc());
   return Result;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 63c10c0..b285d4f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2074,13 +2074,10 @@
   // TODO: don't always clone when decls are refcounted.
   assert(D->getTypeForDecl()->isTemplateTypeParmType());
 
-  TemplateTypeParmDecl *Inst =
-    TemplateTypeParmDecl::Create(SemaRef.Context, Owner,
-                                 D->getLocStart(), D->getLocation(),
-                                 D->getDepth() - TemplateArgs.getNumLevels(),
-                                 D->getIndex(), D->getIdentifier(),
-                                 D->wasDeclaredWithTypename(),
-                                 D->isParameterPack());
+  TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create(
+      SemaRef.Context, Owner, D->getLocStart(), D->getLocation(),
+      D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getIndex(),
+      D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack());
   Inst->setAccess(AS_public);
 
   if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
@@ -2218,17 +2215,14 @@
   if (IsExpandedParameterPack)
     Param = NonTypeTemplateParmDecl::Create(
         SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(),
-        D->getDepth() - TemplateArgs.getNumLevels(), D->getPosition(),
-        D->getIdentifier(), T, DI, ExpandedParameterPackTypes,
+        D->getDepth() - TemplateArgs.getNumSubstitutedLevels(),
+        D->getPosition(), D->getIdentifier(), T, DI, ExpandedParameterPackTypes,
         ExpandedParameterPackTypesAsWritten);
   else
-    Param = NonTypeTemplateParmDecl::Create(SemaRef.Context, Owner,
-                                            D->getInnerLocStart(),
-                                            D->getLocation(),
-                                    D->getDepth() - TemplateArgs.getNumLevels(),
-                                            D->getPosition(),
-                                            D->getIdentifier(), T,
-                                            D->isParameterPack(), DI);
+    Param = NonTypeTemplateParmDecl::Create(
+        SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(),
+        D->getDepth() - TemplateArgs.getNumSubstitutedLevels(),
+        D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI);
 
   Param->setAccess(AS_public);
   if (Invalid)
@@ -2349,19 +2343,15 @@
   // Build the template template parameter.
   TemplateTemplateParmDecl *Param;
   if (IsExpandedParameterPack)
-    Param = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner,
-                                             D->getLocation(),
-                                   D->getDepth() - TemplateArgs.getNumLevels(),
-                                             D->getPosition(),
-                                             D->getIdentifier(), InstParams,
-                                             ExpandedParams);
+    Param = TemplateTemplateParmDecl::Create(
+        SemaRef.Context, Owner, D->getLocation(),
+        D->getDepth() - TemplateArgs.getNumSubstitutedLevels(),
+        D->getPosition(), D->getIdentifier(), InstParams, ExpandedParams);
   else
-    Param = TemplateTemplateParmDecl::Create(SemaRef.Context, Owner,
-                                             D->getLocation(),
-                                   D->getDepth() - TemplateArgs.getNumLevels(),
-                                             D->getPosition(),
-                                             D->isParameterPack(),
-                                             D->getIdentifier(), InstParams);
+    Param = TemplateTemplateParmDecl::Create(
+        SemaRef.Context, Owner, D->getLocation(),
+        D->getDepth() - TemplateArgs.getNumSubstitutedLevels(),
+        D->getPosition(), D->isParameterPack(), D->getIdentifier(), InstParams);
   if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) {
     NestedNameSpecifierLoc QualifierLoc =
         D->getDefaultArgument().getTemplateQualifierLoc();
diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 1205fd1..4afbd2d 100644
--- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -176,3 +176,29 @@
   template <class A> struct T { template<typename B> T(A = 0, B = 0) {} };
   T t(0, 0);
 }
+
+namespace transform_params {
+  template<typename T, T N, template<T (*v)[N]> typename U, T (*X)[N]>
+  struct A { // expected-note 2{{candidate}}
+    template<typename V, V M, V (*Y)[M], template<V (*v)[M]> typename W>
+    A(U<X>, W<Y>); // expected-note {{[with V = int, M = 12, Y = &transform_params::n]}}
+
+    static constexpr T v = N;
+  };
+
+  int n[12];
+  template<int (*)[12]> struct Q {};
+  Q<&n> qn;
+  // FIXME: The class template argument deduction result here is correct, but
+  // we incorrectly fail to deduce arguments for the constructor!
+  A a(qn, qn); // expected-error {{no matching constructor for initialization of 'transform_params::A<int, 12, Q, &transform_params::n>'}}
+  static_assert(a.v == 12);
+
+  // FIXME: This causes a crash right now (not class template deduction related).
+#if 0
+  template<typename ...T> struct B {
+    template<T ...V> B(T (&...p)[V]);
+  };
+  B b({1, 2, 3}, {"foo", "bar"}, {'x', 'y', 'z', 'w'});
+#endif
+}
diff --git a/clang/test/SemaTemplate/deduction.cpp b/clang/test/SemaTemplate/deduction.cpp
index 16e01a9..a1180f0 100644
--- a/clang/test/SemaTemplate/deduction.cpp
+++ b/clang/test/SemaTemplate/deduction.cpp
@@ -481,3 +481,16 @@
   int n;
   void h() { g<0>(Y<0, &n>()); } // expected-error {{no matching function}}
 }
+
+namespace dependent_template_template_param_non_type_param_type {
+  template<int N> struct A { // expected-note 2{{candidate}}
+    template<typename V = int, V M = 12, V (*Y)[M], template<V (*v)[M]> class W>
+    A(W<Y>); // expected-note {{[with V = int, M = 12, Y = &dependent_template_template_param_non_type_param_type::n]}}
+  };
+
+  int n[12];
+  template<int (*)[12]> struct Q {};
+  Q<&n> qn;
+  // FIXME: This should be accepted, but we somehow fail to deduce W.
+  A<0> a(qn); // expected-error {{no matching constructor for initialization}}
+}