c++: improve "NTTP argument considered unused" fix [PR53164, PR105848]
commitb5e38b1c166357e2a63d38ae6da7ae5d68fc115b
authorPatrick Palka <ppalka@redhat.com>
Sat, 1 Apr 2023 14:19:08 +0000 (1 10:19 -0400)
committerPatrick Palka <ppalka@redhat.com>
Sat, 1 Apr 2023 14:19:08 +0000 (1 10:19 -0400)
treeb86d0a39e1c2d9af8db3790ea07bed5283767009
parentb06464c7fb06a049e5d0d2bec4e37282c5ecca8c
c++: improve "NTTP argument considered unused" fix [PR53164, PR105848]

r13-995-g733a792a2b2e16 worked around the problem of (pointer to)
function NTTP arguments not always getting marked as odr-used, by
redundantly calling mark_used on the substituted ADDR_EXPR callee of a
CALL_EXPR.  That is just a narrow workaround however, since it assumes
the function is later called, but the use as a template argument alone
should constitute an odr-use of the function (since template arguments
are an evaluated context, and we're really passing its address); we
shouldn't need to subsequently call or otherwise use the function NTTP
argument.

This patch fixes this in a more general way by walking the template
arguments of each specialization that's about to be instantiated and
redundantly calling mark_used on all entities used within.  As before,
the call to mark_used as it worst a no-op, but it compensates for the
situation where the specialization was first formed in a template context
in which mark_used is inhibited.

Another approach would be to call mark_used whenever we substitute a
TEMPLATE_PARM_INDEX, but that would result in many more redundant calls
to mark_used compared to this approach.  And as the second testcase
below illustrates, we also need to walk C++20 class NTTP arguments which
can be large and thus expensive to walk repeatedly.  The change to
invalid_tparm_referent_p is needed to avoid incorrectly rejecting class
NTTP arguments containing function pointers as in the testcase.

(The third testcase is unrelated to this fix, but it helped rule out an
earlier approach I was considering and it seems we don't have existing
test coverage for this situation.)

PR c++/53164
PR c++/105848

gcc/cp/ChangeLog:

* pt.cc (invalid_tparm_referent_p): Accept ADDR_EXPR of
FUNCTION_DECL.
(instantiate_class_template): Call mark_template_arguments_used.
(tsubst_copy_and_build) <case CALL_EXPR>: Revert r13-995 change.
(mark_template_arguments_used): Define.
(instantiate_body): Call mark_template_arguments_used.

gcc/testsuite/ChangeLog:

* g++.dg/template/fn-ptr3a.C: New test.
* g++.dg/template/fn-ptr3b.C: New test.
* g++.dg/template/fn-ptr4.C: New test.
gcc/cp/pt.cc
gcc/testsuite/g++.dg/template/fn-ptr3a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/fn-ptr3b.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/fn-ptr4.C [new file with mode: 0644]