Message ID | 20220422175032.3106274-1-ppalka@redhat.com |
---|---|
State | New |
Headers |
Return-Path: <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 37E4C3856DCF for <patchwork@sourceware.org>; Fri, 22 Apr 2022 17:51:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 37E4C3856DCF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1650649867; bh=VTHcxDjw3C5jEjAH0GDYaNcGWJY9ou7Di9PWIJmQclQ=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=lszRE9j+4+yNJzyaNaO6jCIoV3WwI/Thh88CNcReBoGkW/Mar910H31Lxx6Yo74Px UbXfmrHa7offC6ArEgTB+dAbTGm9YJxpRbQn46GYGVhiu8lYy0N77lyDL9Bb3/oCPN IcEBW69T8x1RINXyVqdrevNuaRLZ073ICpwtjV54= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id E63943858D37 for <gcc-patches@gcc.gnu.org>; Fri, 22 Apr 2022 17:50:37 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E63943858D37 Received: from mail-qv1-f69.google.com (mail-qv1-f69.google.com [209.85.219.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-671-HeiK3CRJNSO3I_rD8XwgXQ-1; Fri, 22 Apr 2022 13:50:36 -0400 X-MC-Unique: HeiK3CRJNSO3I_rD8XwgXQ-1 Received: by mail-qv1-f69.google.com with SMTP id b8-20020a056214002800b0044666054d36so7162705qvr.12 for <gcc-patches@gcc.gnu.org>; Fri, 22 Apr 2022 10:50:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=VTHcxDjw3C5jEjAH0GDYaNcGWJY9ou7Di9PWIJmQclQ=; b=3DhyUeRw/kWuF/pLXEgt8i19AkGtm4wHCQwz6HR9tD+O8YSM9UrJTmiQEODUkNSHVw CQOX3Mh1VIy/GpD/I4W1LBFX1llCLLcCrxYPHkAXaO9UUcXsMO/4SQqfAoSWiGsnaogQ F4x4uDSLRvG2OVnHLii8lcS/JulMdBFwF84rdcmRjbm8l91atp4VjaIG7/YFaXfgo0ao jokTlWkXili7iHldiuUW8LkHlh0YfSsNWs40wGcbrb+M9D/8K44rqWc2kzHfWih1BBmE OsIxxeLfD8/Nlt4osrdzKlj1LNw0B5Cxm/o2Scvi4tF6pZ/TYyuityEssx52m/YCLEfe axGw== X-Gm-Message-State: AOAM531RltRJUQtUvTvsig/1s7Z9h18XZnqXRtxoCnKQMJ/br7ljDufL KBv445hhMfLTEw4zVjCBFMrbGSHUcVI4U8B4rjWFI6TgWa9TNKQMAj31phzkTRmpcIx3+iRoJc6 4RvL+oP8/bz5vfV9U7k08YH1ONdUci0PeGhMrSQhjn5Lj6ZrkaDbEwx6+oEs34EjXhhM= X-Received: by 2002:ac8:578a:0:b0:2e1:a0d2:c3a with SMTP id v10-20020ac8578a000000b002e1a0d20c3amr4118908qta.261.1650649835522; Fri, 22 Apr 2022 10:50:35 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx0jXR0H/NkZ42nszYRa65jHKIk2lWFTUYqR83MyDZysOJNrKJXJa9LBx3LsmDWlkygdsJO7w== X-Received: by 2002:ac8:578a:0:b0:2e1:a0d2:c3a with SMTP id v10-20020ac8578a000000b002e1a0d20c3amr4118887qta.261.1650649835176; Fri, 22 Apr 2022 10:50:35 -0700 (PDT) Received: from localhost.localdomain (ool-18e40894.dyn.optonline.net. [24.228.8.148]) by smtp.gmail.com with ESMTPSA id m9-20020a05622a118900b002f1fc51135dsm1634325qtk.57.2022.04.22.10.50.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 Apr 2022 10:50:34 -0700 (PDT) To: gcc-patches@gcc.gnu.org Subject: [PATCH] c++: partial ordering with dependent NTTP type [PR105289] Date: Fri, 22 Apr 2022 13:50:32 -0400 Message-Id: <20220422175032.3106274-1-ppalka@redhat.com> X-Mailer: git-send-email 2.36.0.rc2.10.g1ac7422e39 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-14.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> From: Patrick Palka via Gcc-patches <gcc-patches@gcc.gnu.org> Reply-To: Patrick Palka <ppalka@redhat.com> Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> |
Series |
c++: partial ordering with dependent NTTP type [PR105289]
|
|
Commit Message
Patrick Palka
April 22, 2022, 5:50 p.m. UTC
Here ever since r11-6483-ge2e2f3f2c9400f we're rejecting and crashing (respectively) on two testcases that we used to accept in C++17 mode. Both testcases declare partial specializations for which the primary template contains an NTTP with dependent type, but the correctness of these partial specializations is unclear according to PR86193. This patch restores the previous C++17 behavior for such partial specializations by restricting the r11-6483 change to just ordinary deduction as opposed to deduction for sake of partial ordering. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/11? PR c++/105289 PR c++/86193 gcc/cp/ChangeLog: * pt.cc (unify) <case TEMPLATE_PARM_INDEX>: Restrict the r11-6483 change to just ordinary deduction for function templates. When substituting into the NTTP type the second time, use the original type not the substituted type. Remove now unnecessary level check. gcc/testsuite/ChangeLog: * g++.dg/template/partial5.C: Revert r11-6483 change. * g++.dg/template/partial-specialization11.C: New test. * g++.dg/template/partial-specialization12.C: New test. --- gcc/cp/pt.cc | 25 ++++++++++++------- .../template/partial-specialization11.C | 10 ++++++++ .../template/partial-specialization12.C | 12 +++++++++ gcc/testsuite/g++.dg/template/partial5.C | 2 +- 4 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization11.C create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization12.C
Comments
On Fri, 22 Apr 2022, Patrick Palka wrote: > Here ever since r11-6483-ge2e2f3f2c9400f we're rejecting and crashing > (respectively) on two testcases that we used to accept in C++17 mode. > Both testcases declare partial specializations for which the primary > template contains an NTTP with dependent type, but the correctness of > these partial specializations is unclear according to PR86193. > > This patch restores the previous C++17 behavior for such partial > specializations by restricting the r11-6483 change to just ordinary > deduction as opposed to deduction for sake of partial ordering. Note that if we're okay with rejecting such partial specializations even in C++17 mode (and thus deeming PR105289 to be ICE-on-invalid instead of ICE-on-valid), then the fix for the reported ICE is just: diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index dde62ee052d..6d65f6ad3cf 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -24299,7 +24299,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* Now check whether the type of this parameter is still dependent, and give up if so. */ ++processing_template_decl; - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); --processing_template_decl; if (uses_template_parms (tparm)) return unify_success (explain_p); i.e. we need to substitute into the original NTTP type, not into the already substituted NTTP type. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk/11? > > PR c++/105289 > PR c++/86193 > > gcc/cp/ChangeLog: > > * pt.cc (unify) <case TEMPLATE_PARM_INDEX>: Restrict the > r11-6483 change to just ordinary deduction for function > templates. When substituting into the NTTP type the second > time, use the original type not the substituted type. Remove > now unnecessary level check. > > gcc/testsuite/ChangeLog: > > * g++.dg/template/partial5.C: Revert r11-6483 change. > * g++.dg/template/partial-specialization11.C: New test. > * g++.dg/template/partial-specialization12.C: New test. > --- > gcc/cp/pt.cc | 25 ++++++++++++------- > .../template/partial-specialization11.C | 10 ++++++++ > .../template/partial-specialization12.C | 12 +++++++++ > gcc/testsuite/g++.dg/template/partial5.C | 2 +- > 4 files changed, 39 insertions(+), 10 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization11.C > create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization12.C > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index dde62ee052d..52bd130b7e7 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -24287,8 +24287,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, > /* We haven't deduced the type of this parameter yet. */ > if (cxx_dialect >= cxx17 > /* We deduce from array bounds in try_array_deduction. */ > - && !(strict & UNIFY_ALLOW_INTEGER) > - && TEMPLATE_PARM_LEVEL (parm) <= TMPL_ARGS_DEPTH (targs)) > + && !(strict & UNIFY_ALLOW_INTEGER)) > { > /* Deduce it from the non-type argument. As above, ignore > top-level quals here too. */ > @@ -24296,13 +24295,21 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, > RECUR_AND_CHECK_FAILURE (tparms, targs, > tparm, atype, > UNIFY_ALLOW_NONE, explain_p); > - /* Now check whether the type of this parameter is still > - dependent, and give up if so. */ > - ++processing_template_decl; > - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); > - --processing_template_decl; > - if (uses_template_parms (tparm)) > - return unify_success (explain_p); > + if (!processing_template_decl > + && TPARMS_PRIMARY_TEMPLATE (tparms) > + && DECL_FUNCTION_TEMPLATE_P (TPARMS_PRIMARY_TEMPLATE > + (tparms))) > + { > + /* If the NTTP's type uses still-undeduced template > + parameters, then don't unify it now. This gives > + type_unification_real a chance to retry deduction > + with default template arguments substituted in. */ > + ++processing_template_decl; > + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); > + --processing_template_decl; > + if (uses_template_parms (tparm)) > + return unify_success (explain_p); > + } > } > else > /* Try again later. */ > diff --git a/gcc/testsuite/g++.dg/template/partial-specialization11.C b/gcc/testsuite/g++.dg/template/partial-specialization11.C > new file mode 100644 > index 00000000000..20da407d422 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/template/partial-specialization11.C > @@ -0,0 +1,10 @@ > +// PR c++/105289 > + > +template<class T> struct value_type; > + > +template<class T, typename value_type<T>::type V> > +struct push_front_vlist; > + > +template<class T, int V> > +struct push_front_vlist<T*, V> { }; > +// { dg-error "not more specialized" "PR86193" { target c++14_down } .-1 } > diff --git a/gcc/testsuite/g++.dg/template/partial-specialization12.C b/gcc/testsuite/g++.dg/template/partial-specialization12.C > new file mode 100644 > index 00000000000..d70f7592790 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/template/partial-specialization12.C > @@ -0,0 +1,12 @@ > +// PR c++/105289 > +// { dg-do compile { target c++11 } } > + > +template<class T> > +struct value_type; > + > +template <class List, typename value_type<List>::type Element> > +struct push_front_vlist; > + > +template <template <class X, X...> class XList, class T, T Arg, T... Vs> > +struct push_front_vlist<XList<T, Vs...>, Arg> { }; > +// { dg-error "not more specialized" "PR86193" { target c++14_down } .-1 } > diff --git a/gcc/testsuite/g++.dg/template/partial5.C b/gcc/testsuite/g++.dg/template/partial5.C > index 037f684cbd2..7492632f39b 100644 > --- a/gcc/testsuite/g++.dg/template/partial5.C > +++ b/gcc/testsuite/g++.dg/template/partial5.C > @@ -14,7 +14,7 @@ template<typename T, typename T::foo V> > struct Y { }; > > template<typename T, typename U, U v> > -struct Y<T, v> { }; // { dg-error "" } > +struct Y<T, v> { }; // { dg-error "" "PR86193" { target c++14_down } } > > > template<typename T, T V> > -- > 2.36.0.rc2.10.g1ac7422e39 > >
On 4/22/22 15:27, Patrick Palka wrote: > On Fri, 22 Apr 2022, Patrick Palka wrote: > >> Here ever since r11-6483-ge2e2f3f2c9400f we're rejecting and crashing >> (respectively) on two testcases that we used to accept in C++17 mode. >> Both testcases declare partial specializations for which the primary >> template contains an NTTP with dependent type, but the correctness of >> these partial specializations is unclear according to PR86193. >> >> This patch restores the previous C++17 behavior for such partial >> specializations by restricting the r11-6483 change to just ordinary >> deduction as opposed to deduction for sake of partial ordering. > > Note that if we're okay with rejecting such partial specializations even > in C++17 mode (and thus deeming PR105289 to be ICE-on-invalid instead of > ICE-on-valid), then the fix for the reported ICE is just: > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index dde62ee052d..6d65f6ad3cf 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -24299,7 +24299,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, > /* Now check whether the type of this parameter is still > dependent, and give up if so. */ > ++processing_template_decl; > - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); > + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); > --processing_template_decl; > if (uses_template_parms (tparm)) > return unify_success (explain_p); > > i.e. we need to substitute into the original NTTP type, not into the > already substituted NTTP type. I'm happy rejecting partial-specialization12.C on that basis. 11 is interesting because int is a non-dependent type; it might be worth adding that testcase to the DR455 discussion. I think let's go with this patch and bump down the "partial specialization isn't more specialized" diagnostic from permerror to on-by-default pedwarn. >> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for >> trunk/11? >> >> PR c++/105289 >> PR c++/86193 >> >> gcc/cp/ChangeLog: >> >> * pt.cc (unify) <case TEMPLATE_PARM_INDEX>: Restrict the >> r11-6483 change to just ordinary deduction for function >> templates. When substituting into the NTTP type the second >> time, use the original type not the substituted type. Remove >> now unnecessary level check. >> >> gcc/testsuite/ChangeLog: >> >> * g++.dg/template/partial5.C: Revert r11-6483 change. >> * g++.dg/template/partial-specialization11.C: New test. >> * g++.dg/template/partial-specialization12.C: New test. >> --- >> gcc/cp/pt.cc | 25 ++++++++++++------- >> .../template/partial-specialization11.C | 10 ++++++++ >> .../template/partial-specialization12.C | 12 +++++++++ >> gcc/testsuite/g++.dg/template/partial5.C | 2 +- >> 4 files changed, 39 insertions(+), 10 deletions(-) >> create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization11.C >> create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization12.C >> >> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc >> index dde62ee052d..52bd130b7e7 100644 >> --- a/gcc/cp/pt.cc >> +++ b/gcc/cp/pt.cc >> @@ -24287,8 +24287,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, >> /* We haven't deduced the type of this parameter yet. */ >> if (cxx_dialect >= cxx17 >> /* We deduce from array bounds in try_array_deduction. */ >> - && !(strict & UNIFY_ALLOW_INTEGER) >> - && TEMPLATE_PARM_LEVEL (parm) <= TMPL_ARGS_DEPTH (targs)) >> + && !(strict & UNIFY_ALLOW_INTEGER)) >> { >> /* Deduce it from the non-type argument. As above, ignore >> top-level quals here too. */ >> @@ -24296,13 +24295,21 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, >> RECUR_AND_CHECK_FAILURE (tparms, targs, >> tparm, atype, >> UNIFY_ALLOW_NONE, explain_p); >> - /* Now check whether the type of this parameter is still >> - dependent, and give up if so. */ >> - ++processing_template_decl; >> - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); >> - --processing_template_decl; >> - if (uses_template_parms (tparm)) >> - return unify_success (explain_p); >> + if (!processing_template_decl >> + && TPARMS_PRIMARY_TEMPLATE (tparms) >> + && DECL_FUNCTION_TEMPLATE_P (TPARMS_PRIMARY_TEMPLATE >> + (tparms))) >> + { >> + /* If the NTTP's type uses still-undeduced template >> + parameters, then don't unify it now. This gives >> + type_unification_real a chance to retry deduction >> + with default template arguments substituted in. */ >> + ++processing_template_decl; >> + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); >> + --processing_template_decl; >> + if (uses_template_parms (tparm)) >> + return unify_success (explain_p); >> + } >> } >> else >> /* Try again later. */ >> diff --git a/gcc/testsuite/g++.dg/template/partial-specialization11.C b/gcc/testsuite/g++.dg/template/partial-specialization11.C >> new file mode 100644 >> index 00000000000..20da407d422 >> --- /dev/null >> +++ b/gcc/testsuite/g++.dg/template/partial-specialization11.C >> @@ -0,0 +1,10 @@ >> +// PR c++/105289 >> + >> +template<class T> struct value_type; >> + >> +template<class T, typename value_type<T>::type V> >> +struct push_front_vlist; >> + >> +template<class T, int V> >> +struct push_front_vlist<T*, V> { }; >> +// { dg-error "not more specialized" "PR86193" { target c++14_down } .-1 } >> diff --git a/gcc/testsuite/g++.dg/template/partial-specialization12.C b/gcc/testsuite/g++.dg/template/partial-specialization12.C >> new file mode 100644 >> index 00000000000..d70f7592790 >> --- /dev/null >> +++ b/gcc/testsuite/g++.dg/template/partial-specialization12.C >> @@ -0,0 +1,12 @@ >> +// PR c++/105289 >> +// { dg-do compile { target c++11 } } >> + >> +template<class T> >> +struct value_type; >> + >> +template <class List, typename value_type<List>::type Element> >> +struct push_front_vlist; >> + >> +template <template <class X, X...> class XList, class T, T Arg, T... Vs> >> +struct push_front_vlist<XList<T, Vs...>, Arg> { }; >> +// { dg-error "not more specialized" "PR86193" { target c++14_down } .-1 } >> diff --git a/gcc/testsuite/g++.dg/template/partial5.C b/gcc/testsuite/g++.dg/template/partial5.C >> index 037f684cbd2..7492632f39b 100644 >> --- a/gcc/testsuite/g++.dg/template/partial5.C >> +++ b/gcc/testsuite/g++.dg/template/partial5.C >> @@ -14,7 +14,7 @@ template<typename T, typename T::foo V> >> struct Y { }; >> >> template<typename T, typename U, U v> >> -struct Y<T, v> { }; // { dg-error "" } >> +struct Y<T, v> { }; // { dg-error "" "PR86193" { target c++14_down } } >> >> >> template<typename T, T V> >> -- >> 2.36.0.rc2.10.g1ac7422e39 >> >> >
On Mon, 25 Apr 2022, Jason Merrill wrote: > On 4/22/22 15:27, Patrick Palka wrote: > > On Fri, 22 Apr 2022, Patrick Palka wrote: > > > > > Here ever since r11-6483-ge2e2f3f2c9400f we're rejecting and crashing > > > (respectively) on two testcases that we used to accept in C++17 mode. > > > Both testcases declare partial specializations for which the primary > > > template contains an NTTP with dependent type, but the correctness of > > > these partial specializations is unclear according to PR86193. > > > > > > This patch restores the previous C++17 behavior for such partial > > > specializations by restricting the r11-6483 change to just ordinary > > > deduction as opposed to deduction for sake of partial ordering. > > > > Note that if we're okay with rejecting such partial specializations even > > in C++17 mode (and thus deeming PR105289 to be ICE-on-invalid instead of > > ICE-on-valid), then the fix for the reported ICE is just: > > > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > > index dde62ee052d..6d65f6ad3cf 100644 > > --- a/gcc/cp/pt.cc > > +++ b/gcc/cp/pt.cc > > @@ -24299,7 +24299,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, > > int strict, > > /* Now check whether the type of this parameter is still > > dependent, and give up if so. */ > > ++processing_template_decl; > > - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); > > + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); > > --processing_template_decl; > > if (uses_template_parms (tparm)) > > return unify_success (explain_p); > > > > i.e. we need to substitute into the original NTTP type, not into the > > already substituted NTTP type. > > I'm happy rejecting partial-specialization12.C on that basis. 11 is > interesting because int is a non-dependent type; it might be worth adding that > testcase to the DR455 discussion. > > I think let's go with this patch and bump down the "partial specialization > isn't more specialized" diagnostic from permerror to on-by-default pedwarn. Ah, sounds good to me. like so? -- >8 -- Subject: [PATCH] c++: partial ordering with dependent NTTP type [PR105289] Here ever since r11-6483-ge2e2f3f2c9400f we're rejecting and crashing on (respectively) two testcases that we used to accept in C++17 mode since r8-1437-g3da557ec145823. Both testcases declare a partial specialization for which the primary template contains an NTTP with dependent type, but the validity of these partial specializations is unclear and is the subject of PR86193 / CWG 455. This patch just fixes the reported ICE in the second testcase. The bug was that when checking whether the type of an NTTP uses still-undeduced parameters, we'd substitute into the previously substituted NTTP type instead of into the original NTTP type. And given that the treatment of such partial specializations seems to be underspecified in the standard, this patch downgrades the general "not more specialized" diagnostic from a permerror to a pedwarn. Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/11? PR c++/105289 PR c++/86193 gcc/cp/ChangeLog: * pt.cc (process_partial_specialization): Downgrade "partial specialization isn't more specialized" diagnostic from permerror to an on-by-default pedwarn. (unify) <case TEMPLATE_PARM_INDEX>: When substituting into the NTTP type a second time, use the original type not the substituted type. gcc/testsuite/ChangeLog: * g++.dg/template/partial-specialization11.C: New test. * g++.dg/template/partial-specialization12.C: New test. --- gcc/cp/pt.cc | 7 ++++--- .../g++.dg/template/partial-specialization11.C | 11 +++++++++++ .../g++.dg/template/partial-specialization12.C | 13 +++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization11.C create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization12.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index dde62ee052d..7dd9e6788f4 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -5227,8 +5227,9 @@ process_partial_specialization (tree decl) && !get_partial_spec_bindings (maintmpl, maintmpl, specargs)) { auto_diagnostic_group d; - if (permerror (input_location, "partial specialization %qD is not " - "more specialized than", decl)) + if (pedwarn (input_location, 0, + "partial specialization %qD is not more specialized than", + decl)) inform (DECL_SOURCE_LOCATION (maintmpl), "primary template %qD", maintmpl); } @@ -24299,7 +24300,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* Now check whether the type of this parameter is still dependent, and give up if so. */ ++processing_template_decl; - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); --processing_template_decl; if (uses_template_parms (tparm)) return unify_success (explain_p); diff --git a/gcc/testsuite/g++.dg/template/partial-specialization11.C b/gcc/testsuite/g++.dg/template/partial-specialization11.C new file mode 100644 index 00000000000..df1ead380f1 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/partial-specialization11.C @@ -0,0 +1,11 @@ +// PR c++/86193 +// CWG 455 (active) +// { dg-options "" } // clear -pedantic-errors + +template<class T> struct value_type; + +template<class T, typename value_type<T>::type V> +struct push_front_vlist; + +template<class T, int V> +struct push_front_vlist<T*, V> { }; // { dg-warning "not more specialized" } diff --git a/gcc/testsuite/g++.dg/template/partial-specialization12.C b/gcc/testsuite/g++.dg/template/partial-specialization12.C new file mode 100644 index 00000000000..6e84f4949c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/partial-specialization12.C @@ -0,0 +1,13 @@ +// PR c++/105289 +// PR c++/86193 +// CWG 455 (active) +// { dg-do compile { target c++11 } } + +template<class T> +struct value_type; + +template <class List, typename value_type<List>::type Element> +struct push_front_vlist; + +template <template <class X, X...> class XList, class T, T Arg, T... Vs> +struct push_front_vlist<XList<T, Vs...>, Arg> { }; // { dg-error "not more specialized" }
On 4/25/22 14:10, Patrick Palka wrote: > On Mon, 25 Apr 2022, Jason Merrill wrote: > >> On 4/22/22 15:27, Patrick Palka wrote: >>> On Fri, 22 Apr 2022, Patrick Palka wrote: >>> >>>> Here ever since r11-6483-ge2e2f3f2c9400f we're rejecting and crashing >>>> (respectively) on two testcases that we used to accept in C++17 mode. >>>> Both testcases declare partial specializations for which the primary >>>> template contains an NTTP with dependent type, but the correctness of >>>> these partial specializations is unclear according to PR86193. >>>> >>>> This patch restores the previous C++17 behavior for such partial >>>> specializations by restricting the r11-6483 change to just ordinary >>>> deduction as opposed to deduction for sake of partial ordering. >>> >>> Note that if we're okay with rejecting such partial specializations even >>> in C++17 mode (and thus deeming PR105289 to be ICE-on-invalid instead of >>> ICE-on-valid), then the fix for the reported ICE is just: >>> >>> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc >>> index dde62ee052d..6d65f6ad3cf 100644 >>> --- a/gcc/cp/pt.cc >>> +++ b/gcc/cp/pt.cc >>> @@ -24299,7 +24299,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, >>> int strict, >>> /* Now check whether the type of this parameter is still >>> dependent, and give up if so. */ >>> ++processing_template_decl; >>> - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); >>> + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); >>> --processing_template_decl; >>> if (uses_template_parms (tparm)) >>> return unify_success (explain_p); >>> >>> i.e. we need to substitute into the original NTTP type, not into the >>> already substituted NTTP type. >> >> I'm happy rejecting partial-specialization12.C on that basis. 11 is >> interesting because int is a non-dependent type; it might be worth adding that >> testcase to the DR455 discussion. >> >> I think let's go with this patch and bump down the "partial specialization >> isn't more specialized" diagnostic from permerror to on-by-default pedwarn. > > Ah, sounds good to me. like so? > > -- >8 -- > > Subject: [PATCH] c++: partial ordering with dependent NTTP type [PR105289] > > Here ever since r11-6483-ge2e2f3f2c9400f we're rejecting and crashing > on (respectively) two testcases that we used to accept in C++17 mode > since r8-1437-g3da557ec145823. Both testcases declare a partial > specialization for which the primary template contains an NTTP with > dependent type, but the validity of these partial specializations is > unclear and is the subject of PR86193 / CWG 455. > > This patch just fixes the reported ICE in the second testcase. The bug > was that when checking whether the type of an NTTP uses still-undeduced > parameters, we'd substitute into the previously substituted NTTP type > instead of into the original NTTP type. > > And given that the treatment of such partial specializations seems to > be underspecified in the standard, this patch downgrades the general > "not more specialized" diagnostic from a permerror to a pedwarn. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk/11? OK. > PR c++/105289 > PR c++/86193 > > gcc/cp/ChangeLog: > > * pt.cc (process_partial_specialization): Downgrade "partial > specialization isn't more specialized" diagnostic from permerror > to an on-by-default pedwarn. > (unify) <case TEMPLATE_PARM_INDEX>: When substituting into the > NTTP type a second time, use the original type not the > substituted type. > > gcc/testsuite/ChangeLog: > > * g++.dg/template/partial-specialization11.C: New test. > * g++.dg/template/partial-specialization12.C: New test. > --- > gcc/cp/pt.cc | 7 ++++--- > .../g++.dg/template/partial-specialization11.C | 11 +++++++++++ > .../g++.dg/template/partial-specialization12.C | 13 +++++++++++++ > 3 files changed, 28 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization11.C > create mode 100644 gcc/testsuite/g++.dg/template/partial-specialization12.C > > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc > index dde62ee052d..7dd9e6788f4 100644 > --- a/gcc/cp/pt.cc > +++ b/gcc/cp/pt.cc > @@ -5227,8 +5227,9 @@ process_partial_specialization (tree decl) > && !get_partial_spec_bindings (maintmpl, maintmpl, specargs)) > { > auto_diagnostic_group d; > - if (permerror (input_location, "partial specialization %qD is not " > - "more specialized than", decl)) > + if (pedwarn (input_location, 0, > + "partial specialization %qD is not more specialized than", > + decl)) > inform (DECL_SOURCE_LOCATION (maintmpl), "primary template %qD", > maintmpl); > } > @@ -24299,7 +24300,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, > /* Now check whether the type of this parameter is still > dependent, and give up if so. */ > ++processing_template_decl; > - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); > + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); > --processing_template_decl; > if (uses_template_parms (tparm)) > return unify_success (explain_p); > diff --git a/gcc/testsuite/g++.dg/template/partial-specialization11.C b/gcc/testsuite/g++.dg/template/partial-specialization11.C > new file mode 100644 > index 00000000000..df1ead380f1 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/template/partial-specialization11.C > @@ -0,0 +1,11 @@ > +// PR c++/86193 > +// CWG 455 (active) > +// { dg-options "" } // clear -pedantic-errors > + > +template<class T> struct value_type; > + > +template<class T, typename value_type<T>::type V> > +struct push_front_vlist; > + > +template<class T, int V> > +struct push_front_vlist<T*, V> { }; // { dg-warning "not more specialized" } > diff --git a/gcc/testsuite/g++.dg/template/partial-specialization12.C b/gcc/testsuite/g++.dg/template/partial-specialization12.C > new file mode 100644 > index 00000000000..6e84f4949c1 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/template/partial-specialization12.C > @@ -0,0 +1,13 @@ > +// PR c++/105289 > +// PR c++/86193 > +// CWG 455 (active) > +// { dg-do compile { target c++11 } } > + > +template<class T> > +struct value_type; > + > +template <class List, typename value_type<List>::type Element> > +struct push_front_vlist; > + > +template <template <class X, X...> class XList, class T, T Arg, T... Vs> > +struct push_front_vlist<XList<T, Vs...>, Arg> { }; // { dg-error "not more specialized" }
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index dde62ee052d..52bd130b7e7 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -24287,8 +24287,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* We haven't deduced the type of this parameter yet. */ if (cxx_dialect >= cxx17 /* We deduce from array bounds in try_array_deduction. */ - && !(strict & UNIFY_ALLOW_INTEGER) - && TEMPLATE_PARM_LEVEL (parm) <= TMPL_ARGS_DEPTH (targs)) + && !(strict & UNIFY_ALLOW_INTEGER)) { /* Deduce it from the non-type argument. As above, ignore top-level quals here too. */ @@ -24296,13 +24295,21 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, RECUR_AND_CHECK_FAILURE (tparms, targs, tparm, atype, UNIFY_ALLOW_NONE, explain_p); - /* Now check whether the type of this parameter is still - dependent, and give up if so. */ - ++processing_template_decl; - tparm = tsubst (tparm, targs, tf_none, NULL_TREE); - --processing_template_decl; - if (uses_template_parms (tparm)) - return unify_success (explain_p); + if (!processing_template_decl + && TPARMS_PRIMARY_TEMPLATE (tparms) + && DECL_FUNCTION_TEMPLATE_P (TPARMS_PRIMARY_TEMPLATE + (tparms))) + { + /* If the NTTP's type uses still-undeduced template + parameters, then don't unify it now. This gives + type_unification_real a chance to retry deduction + with default template arguments substituted in. */ + ++processing_template_decl; + tparm = tsubst (TREE_TYPE (parm), targs, tf_none, NULL_TREE); + --processing_template_decl; + if (uses_template_parms (tparm)) + return unify_success (explain_p); + } } else /* Try again later. */ diff --git a/gcc/testsuite/g++.dg/template/partial-specialization11.C b/gcc/testsuite/g++.dg/template/partial-specialization11.C new file mode 100644 index 00000000000..20da407d422 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/partial-specialization11.C @@ -0,0 +1,10 @@ +// PR c++/105289 + +template<class T> struct value_type; + +template<class T, typename value_type<T>::type V> +struct push_front_vlist; + +template<class T, int V> +struct push_front_vlist<T*, V> { }; +// { dg-error "not more specialized" "PR86193" { target c++14_down } .-1 } diff --git a/gcc/testsuite/g++.dg/template/partial-specialization12.C b/gcc/testsuite/g++.dg/template/partial-specialization12.C new file mode 100644 index 00000000000..d70f7592790 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/partial-specialization12.C @@ -0,0 +1,12 @@ +// PR c++/105289 +// { dg-do compile { target c++11 } } + +template<class T> +struct value_type; + +template <class List, typename value_type<List>::type Element> +struct push_front_vlist; + +template <template <class X, X...> class XList, class T, T Arg, T... Vs> +struct push_front_vlist<XList<T, Vs...>, Arg> { }; +// { dg-error "not more specialized" "PR86193" { target c++14_down } .-1 } diff --git a/gcc/testsuite/g++.dg/template/partial5.C b/gcc/testsuite/g++.dg/template/partial5.C index 037f684cbd2..7492632f39b 100644 --- a/gcc/testsuite/g++.dg/template/partial5.C +++ b/gcc/testsuite/g++.dg/template/partial5.C @@ -14,7 +14,7 @@ template<typename T, typename T::foo V> struct Y { }; template<typename T, typename U, U v> -struct Y<T, v> { }; // { dg-error "" } +struct Y<T, v> { }; // { dg-error "" "PR86193" { target c++14_down } } template<typename T, T V>