[PATCH] c++: odr-use argument to a function NTTP [PR53164]

Patrick Palka ppalka@redhat.com
Tue Oct 5 19:17:12 GMT 2021


On Mon, 4 Oct 2021, Patrick Palka wrote:

> When passing a function template as the argument to a function NTTP
> inside a template, we resolve it to the right specialization ahead of
> time via resolve_address_of_overloaded_function, though the call to
> mark_used within defers odr-using it until instantiation time (as usual).
> But at instantiation time we end up never calling mark_used on the
> specialization.
> 
> This patch fixes this by adding a call to mark_used in
> convert_nontype_argument_function.
> 
> 	PR c++/53164
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.c (convert_nontype_argument_function): Call mark_used.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/template/non-dependent16.C: New test.
> ---
>  gcc/cp/pt.c                                     |  3 +++
>  gcc/testsuite/g++.dg/template/non-dependent16.C | 16 ++++++++++++++++
>  2 files changed, 19 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/template/non-dependent16.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index f950f4a21b7..5e819c9598c 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -6668,6 +6668,9 @@ convert_nontype_argument_function (tree type, tree expr,
>        return NULL_TREE;
>      }
>  
> +  if (!mark_used (fn_no_ptr, complain) && !(complain & tf_error))
> +    return NULL_TREE;
> +
>    linkage = decl_linkage (fn_no_ptr);
>    if (cxx_dialect >= cxx11 ? linkage == lk_none : linkage != lk_external)
>      {
> diff --git a/gcc/testsuite/g++.dg/template/non-dependent16.C b/gcc/testsuite/g++.dg/template/non-dependent16.C
> new file mode 100644
> index 00000000000..b7dca8f6752
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/non-dependent16.C
> @@ -0,0 +1,16 @@
> +// PR c++/53164
> +
> +template<class T>
> +void f(T) {
> +  T::fail; // { dg-error "not a member" }
> +}
> +
> +template<void(int)>
> +struct A { };
> +
> +template<int>
> +void g() {
> +  A<f> a;
> +}

I should mention that the original testcase in the PR was slightly
different than this one in that it also performed a call to the NTTP,
e.g.

  template<void p(int)>
  struct A {
    static void h() {
      p(0);
    }
  };

  template<int>
  void g() {
    A<f>::h();
  }

  templated void g<0>();

and not even the call was enough to odr-use f, apparently because the
CALL_EXPR case of tsubst_expr calls mark_used on the callee only when
it's a FUNCTION_DECL, but in this case after substitution it's an
ADDR_EXPR of a FUNCTION_DECL.  Fixing this by looking through the ADDR_EXPR
worked, but IIUC the call isn't necessary for f to be odr-used, simply
using f as a template argument should be sufficient, so it seems the
above is better fix.

> +
> +template void g<0>();
> -- 
> 2.33.0.610.gcefe983a32
> 
> 



More information about the Gcc-patches mailing list