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 > >