On Mon, Mar 5, 2018 at 7:05 PM, Martin Sebor <mse...@gmail.com> wrote:
> On 02/23/2018 07:32 PM, Jason Merrill wrote:
>> On Sun, Feb 18, 2018 at 11:39 PM, Jason Merrill <ja...@redhat.com> wrote:
>>> On Fri, Feb 16, 2018 at 4:33 PM, Martin Sebor <mse...@gmail.com> wrote:
>>>> On 02/16/2018 07:04 AM, Jason Merrill wrote:
>>>>>
>>>>> On Thu, Feb 15, 2018 at 6:36 PM, Martin Sebor <mse...@gmail.com> wrote:
>>>>>>
>>>>>>
>>>>>> A failed template deduction in template member of a template
>>>>>> triggers an ICE with -std=c++17 due to what seems like
>>>>>> a missing handling of invalid input.  Replacing
>>>>>> the gcc_unreachable() call that causes the ICE with a return
>>>>>> statement indicating the deduction failure eliminates the ICE
>>>>>> and restores sane diagnostics.
>>>>>
>>>>>
>>>>>
>>>>> Hmm, we really shouldn't have gotten there; that assert is checking
>>>>> that when we see a TEMPLATE_*_PARM node in the template signature, it
>>>>> corresponds to one of the actual parms of the template.  Sounds like
>>>>> something is going wrong in build_deduction_guide.
>>>>
>>>>
>>>>
>>>> Are you suggesting that build_deduction_guide should fail somehow
>>>> (it's not expected to fail right now) or that the guide it creates
>>>> is wrong?
>>>
>>>
>>> The latter.  Maybe we're handling T wrong somehow?  We shouldn't be
>>> trying to deduce it.  In fact, we probably shouldn't be trying to
>>> deduce arguments for 'b' until we instantiate A.
>>
>>
>> Looks like the problem is that when we substitute into the
>> TEMPLATE_TYPE_PARM representing 'B' in the function, we don't touch
>> CLASS_PLACEHOLDER_TEMPLATE:
>>
>>                     else if (tree pl = CLASS_PLACEHOLDER_TEMPLATE (t))
>>                       {
>>                         if (DECL_TEMPLATE_TEMPLATE_PARM_P (pl))
>>                           pl = tsubst (pl, args, complain, in_decl);
>>                         CLASS_PLACEHOLDER_TEMPLATE (r) = pl;
>>                       }
>>
>> This code is failing to replace A<T>::B with A<int>::B.
>
> I don't know what to do here/what you're suggesting.  Before
> the call to tsubst() pl is a TEMPLATE_DECL of struct A<T>::B.
> Calling tsubst() works and replaces the ICE with a reasonable
> error but then causes an ICE in cpp1z/class-deduction19.C.
> There, pl is also TEMPLATE_DECL, and I'm not sure how to
> differentiate between the two at this level.

The problem is that tsubst calls tsubst_decl, which tries to generate
a new instantiated declaration; since this is a use, we need to use
tsubst_copy instead.

Jason
commit 5e194d897e76c8a54a14a50b3a6cb94a21e6810d
Author: Jason Merrill <ja...@redhat.com>
Date:   Sun Mar 11 21:43:32 2018 -0400

            PR c++/84355 - ICE with deduction for member class template.
    
            * pt.c (tsubst) [TEMPLATE_TYPE_PARM]: Always substitute into
            CLASS_PLACEHOLDER_TEMPLATE.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a92b36a6031..4640ca08ce0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14125,8 +14125,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 			= tsubst_constraint (constr, args, complain, in_decl);
 		    else if (tree pl = CLASS_PLACEHOLDER_TEMPLATE (t))
 		      {
-			if (DECL_TEMPLATE_TEMPLATE_PARM_P (pl))
-			  pl = tsubst (pl, args, complain, in_decl);
+			pl = tsubst_copy (pl, args, complain, in_decl);
 			CLASS_PLACEHOLDER_TEMPLATE (r) = pl;
 		      }
 		  }
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction50.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction50.C
new file mode 100644
index 00000000000..e8cdd8c710f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction50.C
@@ -0,0 +1,22 @@
+// PR c++/84355
+// { dg-additional-options -std=c++17 }
+
+template <class, class> struct same;
+template <class T> struct same<T,T> {};
+
+template<typename T> struct A
+{
+  template<class U> struct B
+  {
+    B(U);
+  };
+
+  A() {
+    B b(0);
+    same<decltype(b),B<int>>{};
+  }
+};
+
+struct C {};
+
+A<C> a;

Reply via email to