[PATCH] c++: converted lambda as template argument [PR83258, ...]
Jason Merrill
jason@redhat.com
Wed May 10 21:23:19 GMT 2023
On 5/10/23 14:11, Patrick Palka wrote:
> On Wed, 10 May 2023, Jason Merrill wrote:
>
>> On 5/10/23 11:36, Patrick Palka wrote:
>>> r8-1253-g3d2e25a240c711 removed the template argument linkage requirement
>>> in convert_nontype_argument for C++17, but we need to also remove the one
>>> in convert_nontype_argument_function for sake of the first and third test
>>> case which we incorrectly reject (in C++17/20 mode).
>>>
>>> And in invalid_tparm_referent_p we're inadvertendly rejecting using the
>>> address of a lambda's static op() due to the DECL_ARTIFICIAL check.
>>> This patch relaxes this check for sake of the second test case which we
>>> incorrectly reject (in C++20 mode).
>>>
>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
>>> trunk and perhaps 13 (since it's a relatively easy/safe fix for a
>>> popular non-regression bug).
>>>
>>> Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
>>>
>>> PR c++/83258
>>> PR c++/80488
>>> PR c++/97700
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> * pt.cc (convert_nontype_argument_function): Disable linkage
>>> requirement for C++17 and later.
>>> (invalid_tparm_referent_p): Relax DECL_ARTIFICIAL check for
>>> the artificial static op() of a lambda.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> * g++.dg/ext/visibility/anon8.C: Don't expect a "no linkage"
>>> error for the template argument &B2:fn in C++17 mode.
>>> * g++.dg/cpp0x/lambda/lambda-conv15.C: New test.
>>> * g++.dg/cpp2a/nontype-class56.C: New test.
>>> * g++.dg/template/function2.C: New test.
>>> ---
>>> gcc/cp/pt.cc | 7 +++++--
>>> gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv15.C | 11 +++++++++++
>>> gcc/testsuite/g++.dg/cpp2a/nontype-class56.C | 8 ++++++++
>>> gcc/testsuite/g++.dg/ext/visibility/anon8.C | 4 ++--
>>> gcc/testsuite/g++.dg/template/function2.C | 8 ++++++++
>>> 5 files changed, 34 insertions(+), 4 deletions(-)
>>> create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv15.C
>>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class56.C
>>> create mode 100644 gcc/testsuite/g++.dg/template/function2.C
>>>
>>> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
>>> index 696df2bdd9f..c9b089f8fa7 100644
>>> --- a/gcc/cp/pt.cc
>>> +++ b/gcc/cp/pt.cc
>>> @@ -6782,7 +6782,8 @@ convert_nontype_argument_function (tree type, tree
>>> expr,
>>> }
>>> linkage = decl_linkage (fn_no_ptr);
>>> - if (cxx_dialect >= cxx11 ? linkage == lk_none : linkage != lk_external)
>>> + if ((cxx_dialect < cxx11 && linkage != lk_external)
>>> + || (cxx_dialect < cxx17 && linkage == lk_none))
>>> {
>>> if (complain & tf_error)
>>> {
>>> @@ -7180,7 +7181,9 @@ invalid_tparm_referent_p (tree type, tree expr,
>>> tsubst_flags_t complain)
>>> * a string literal (5.13.5),
>>> * the result of a typeid expression (8.2.8), or
>>> * a predefined __func__ variable (11.4.1). */
>>> - else if (DECL_ARTIFICIAL (decl))
>>> + else if (DECL_ARTIFICIAL (decl)
>>> + /* Accept the artificial static op() of a lambda. */
>>> + && !LAMBDA_TYPE_P (CP_DECL_CONTEXT (decl)))
>>
>> Maybe check for FUNCTION_DECL instead? I think the cases we want to diagnose
>> are all VAR_DECL.
>
> Makes sense, before r13-6970-gb5e38b1c166357 this code path would only
> be reachable for VAR_DECL anyway. Like so? Bootstrapped and regtested
> on x86_64-pc-linux-gnu, does this look OK for trunk and perhaps 13?
OK for both.
> -- >8 --
>
> Subject: [PATCH] c++: converted lambda as template argument [PR83258, ...]
>
> r8-1253-g3d2e25a240c711 removed the template argument linkage requirement
> in convert_nontype_argument for C++17, but we need to also remove the one
> in convert_nontype_argument_function for sake of the first and third test
> case which we incorrectly reject (in C++17/20 mode).
>
> And in invalid_tparm_referent_p we're inadvertendly diagnosing using the
> address of a lambda's static op() since it's DECL_ARTIFICIAL, which causes
> us to reject the second (C++20) testcase. But this DECL_ARTIFICIAL check
> seems to be relevant only for VAR_DECL, and indeed code path was reached
> only for VAR_DECL until r13-6970-gb5e38b1c166357. So this patch relaxes
> the check accordingly.
>
> Co-authored-by: Jonathan Wakely <jwakely@redhat.com>
>
> PR c++/83258
> PR c++/80488
> PR c++/97700
>
> gcc/cp/ChangeLog:
>
> * pt.cc (convert_nontype_argument_function): Disable linkage
> check for C++17 and later.
> (invalid_tparm_referent_p): Accept DECL_ARTIFICIAL FUNCTION_DECL.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/ext/visibility/anon8.C: Don't expect a "no linkage"
> error for the template argument &B2:fn in C++17 mode.
> * g++.dg/cpp0x/lambda/lambda-conv15.C: New test.
> * g++.dg/cpp2a/nontype-class56.C: New test.
> * g++.dg/template/function2.C: New test.
> ---
> gcc/cp/pt.cc | 5 +++--
> gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv15.C | 11 +++++++++++
> gcc/testsuite/g++.dg/cpp2a/nontype-class56.C | 8 ++++++++
> gcc/testsuite/g++.dg/ext/visibility/anon8.C | 4 ++--
> gcc/testsuite/g++.dg/template/function2.C | 8 ++++++++
> 5 files changed, 32 insertions(+), 4 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv15.C
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class56.C
> create mode 100644 gcc/testsuite/g++.dg/template/function2.C
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 696df2bdd9f..351fc18b600 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -6782,7 +6782,8 @@ convert_nontype_argument_function (tree type, tree expr,
> }
>
> linkage = decl_linkage (fn_no_ptr);
> - if (cxx_dialect >= cxx11 ? linkage == lk_none : linkage != lk_external)
> + if ((cxx_dialect < cxx11 && linkage != lk_external)
> + || (cxx_dialect < cxx17 && linkage == lk_none))
> {
> if (complain & tf_error)
> {
> @@ -7180,7 +7181,7 @@ invalid_tparm_referent_p (tree type, tree expr, tsubst_flags_t complain)
> * a string literal (5.13.5),
> * the result of a typeid expression (8.2.8), or
> * a predefined __func__ variable (11.4.1). */
> - else if (DECL_ARTIFICIAL (decl))
> + else if (VAR_P (decl) && DECL_ARTIFICIAL (decl))
> {
> if (complain & tf_error)
> error ("the address of %qD is not a valid template argument",
> diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv15.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv15.C
> new file mode 100644
> index 00000000000..cf45e06a33d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-conv15.C
> @@ -0,0 +1,11 @@
> +// PR c++/83258
> +// PR c++/80488
> +// { dg-do compile { target c++11 } }
> +
> +template<void(*)()> struct A { };
> +
> +int main() {
> + constexpr auto fp = +[]{}; // { dg-error "non-'constexpr' function" "" { target c++14_down } }
> + A<fp> a1; // { dg-error "not a valid template argument" "" { target c++14_down } }
> + A<[]{}> a2; // { dg-error "lambda-expression in template-argument|invalid" "" { target c++17_down } }
> +}
> diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class56.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class56.C
> new file mode 100644
> index 00000000000..0efd735c8a3
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class56.C
> @@ -0,0 +1,8 @@
> +// PR c++/97700
> +// { dg-do compile { target c++20 } }
> +
> +struct S { void (*f)(); };
> +
> +template<S> struct X { };
> +
> +X<S{[]{}}> x;
> diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon8.C b/gcc/testsuite/g++.dg/ext/visibility/anon8.C
> index b8507497d32..bfcc2d06df6 100644
> --- a/gcc/testsuite/g++.dg/ext/visibility/anon8.C
> +++ b/gcc/testsuite/g++.dg/ext/visibility/anon8.C
> @@ -2,7 +2,7 @@
> // { dg-do compile }
>
> template <void (*fn) ()>
> -void call () // { dg-message "note" }
> +void call () // { dg-message "note" "" { target c++14_down } }
> {
> fn ();
> }
> @@ -26,7 +26,7 @@ int main ()
> static void fn2 () {}
> };
> call<&B1::fn1> ();
> - call<&B2::fn2> (); // { dg-error "linkage|no matching" }
> + call<&B2::fn2> (); // { dg-error "linkage|no matching" "" { target c++14_down } }
> call<&fn3> ();
> call<&B1::fn4> ();
> call<&fn5> (); // { dg-error "linkage|no matching" "" { target { ! c++11 } } }
> diff --git a/gcc/testsuite/g++.dg/template/function2.C b/gcc/testsuite/g++.dg/template/function2.C
> new file mode 100644
> index 00000000000..54c48e6b36f
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/function2.C
> @@ -0,0 +1,8 @@
> +// PR c++/83258
> +
> +template<void(*)()> struct A { };
> +
> +int main() {
> + struct B { static void f() { } };
> + A<B::f> a; // { dg-error "linkage" "" { target c++14_down } }
> +}
More information about the Gcc-patches
mailing list