[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