On Mar 29, 2018, Alexandre Oliva <aol...@redhat.com> wrote: > On Mar 28, 2018, Jason Merrill <ja...@redhat.com> wrote: >> It looks like cp_build_addr_expr_1 already calls mark_used for single >> static member functions, it should probably do the same for single >> non-member functions.
> ultimately select, *if* we marked anything. But since we've peeled off > the baseline, the test ^ err, baselink > if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF) > passes because FUNCTION_DECL is not COMPONENT_REF, and we call > build_address before we get a chance to mark anything. ... unless we're at the case it's supposed to catch, namely when we call obj.static_memfn() ;-) Here's a patch that should take care of the marking a namespace-scoped or static member function as used when taking its address, thus working around (fixing?) the reported problem. Regstrapping now. Ok to install if it passes? [PR c++/84943] mark function as used when taking its address fn[0]() ICEd because we would fold the INDIRECT_REF used for the array indexing while building the address for the call, after not finding the decl hiding there at first. But the decl would be exposed by the folding, and then lower layers would complain we had the decl, after all, but it wasn't one of the artificial or special functions that could be called without being marked as used. This patch arranges for a FUNCTION_DECL to be marked as used when taking its address, just like we already did when taking the address of a static function to call it as a member function (i.e. using the obj.fn() notation). for gcc/cp/ChangeLog PR c++/84943 * typeck.c (cp_build_addr_expr_1): Mark FUNCTION_DECL as used. for gcc/testsuite/ChangeLog PR c++/84943 * g++.dg/pr84943.C: New. * g++.dg/pr84943-2.C: New. --- gcc/cp/typeck.c | 8 ++++- gcc/testsuite/g++.dg/pr84943-2.C | 64 ++++++++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/pr84943.C | 8 +++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/pr84943-2.C create mode 100644 gcc/testsuite/g++.dg/pr84943.C diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d3183b5321d3..d6157772c0f3 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5831,6 +5831,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) if (type_unknown_p (arg)) return build1 (ADDR_EXPR, unknown_type_node, arg); + tree maybe_overloaded_arg = arg; + if (TREE_CODE (arg) == OFFSET_REF) /* We want a pointer to member; bypass all the code for actually taking the address of something. */ @@ -5971,6 +5973,9 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) so we can just form an ADDR_EXPR with the correct type. */ if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF) { + if (TREE_CODE (arg) == FUNCTION_DECL && arg == maybe_overloaded_arg + && !mark_used (arg, complain) && !(complain & tf_error)) + return error_mark_node; val = build_address (arg); if (TREE_CODE (arg) == OFFSET_REF) PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); @@ -5983,7 +5988,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) function. */ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (fn)); - if (!mark_used (fn, complain) && !(complain & tf_error)) + if (arg == maybe_overloaded_arg + && !mark_used (fn, complain) && !(complain & tf_error)) return error_mark_node; val = build_address (fn); if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) diff --git a/gcc/testsuite/g++.dg/pr84943-2.C b/gcc/testsuite/g++.dg/pr84943-2.C new file mode 100644 index 000000000000..d1ef012b9155 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr84943-2.C @@ -0,0 +1,64 @@ +// { dg-do run } + +// Avoid -pedantic-error default +// { dg-options "" } + +// Make sure the functions referenced by various forms of +// address-taking are marked as used and compiled in. + +static void ac() {} +void a() { + ac[0](); // { dg-warning "arithmetic" } +} + +static void bc() {} +void b() { + (&*&*&*&bc)(); +} + +template <typename U> U cc() {} +void (*c())() { + return cc; +} + +template <typename T> +struct x { + void a(int); + template <typename U> static U a(x*) {} + static void a(long) {} + static void a(void *) {} + static void a() { + void (*p0)(void*) = x().a; + p0(0); + void (*p1)(long) = a; + p1(0); + void (*p2)() = a; + p2(); + void (*p3)(x*) = a; + p3(0); + } +}; + +struct z { + void a(int); + template <typename U> static U a(z*) {} + static void a(long) {} + static void a(void *) {} + static void a() { + void (*p0)(void*) = z().a; + p0(0); + void (*p1)(long) = a; + p1(0); + void (*p2)() = a; + p2(); + void (*p3)(z*) = a; + p3(0); + } +}; + +int main(int argc, char *argv[]) { + if (argc > 1) { + x<void>().a(); + z().a(); + } +} diff --git a/gcc/testsuite/g++.dg/pr84943.C b/gcc/testsuite/g++.dg/pr84943.C new file mode 100644 index 000000000000..36f75a164119 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr84943.C @@ -0,0 +1,8 @@ +// { dg-do compile } + +// Avoid -pedantic-error default +// { dg-options "" } + +void a() { + a[0](); // { dg-warning "arithmetic" } +} -- Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/ You must be the change you wish to see in the world. -- Gandhi Be Free! -- http://FSFLA.org/ FSF Latin America board member Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer