On Apr 2, 2018, Jason Merrill <ja...@redhat.com> wrote: > On Sat, Mar 31, 2018 at 2:24 AM, Alexandre Oliva <aol...@redhat.com> wrote: >> On Mar 30, 2018, Jason Merrill <ja...@redhat.com> wrote: >> >>> I don't think we need this; if arg is overloaded, we take the >>> type_unknown_p early exit, so the code lower down is always dealing >>> with a single function. >> >> Aah, that's why it seemed to me that we had already resolved overloads >> when we got there. >> >> As a bonus, I added the tf_conv test before another mark_used call I'd >> missed in the previous patch.
> What if we check tf_conv in mark_used itself rather than at all the call > sites? There are other uses of mark_used, but presumably we want them all to be more conservative under tf_conv, so... Here's what I'm testing. Ok 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). However, we shouldn't mark functions as used when just performing overload resolution, lest we might instantiate templates we shouldn't, as in g++.dg/overload/template1.C, so we adjust mark_used to return early when testing conversions. for gcc/cp/ChangeLog PR c++/84943 * typeck.c (cp_build_addr_expr_1): Mark FUNCTION_DECL as used. * decl2.c (mark_used): Return without effects if tf_conv. for gcc/testsuite/ChangeLog PR c++/84943 * g++.dg/pr84943.C: New. * g++.dg/pr84943-2.C: New. --- gcc/cp/decl2.c | 6 ++++ gcc/cp/typeck.c | 3 ++ gcc/testsuite/g++.dg/pr84943-2.C | 64 ++++++++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/pr84943.C | 8 +++++ 4 files changed, 81 insertions(+) create mode 100644 gcc/testsuite/g++.dg/pr84943-2.C create mode 100644 gcc/testsuite/g++.dg/pr84943.C diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index fa753749e1a6..740e85b35617 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -5201,6 +5201,12 @@ maybe_instantiate_decl (tree decl) bool mark_used (tree decl, tsubst_flags_t complain) { + /* If we're just testing conversions or resolving overloads, we + don't want any permanent effects like forcing functions to be + output or instantiating templates. */ + if ((complain & tf_conv)) + return false; + /* If DECL is a BASELINK for a single function, then treat it just like the DECL for the function. Otherwise, if the BASELINK is for an overloaded function, we don't know which function was diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d454c6c5a295..bd67b82fcc65 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5971,6 +5971,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 + && !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); 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