Hi! The following testcase ICEs, because while we have in cp_build_addr_expr_1 diagnostics for taking address of an immediate function (and as an exception deal with build_address from immediate invocation), I forgot to diagnose taking address of a member function which is done in a different place. I hope (s.*&S::foo) () is not an immediate invocation like (*&foo) () is not, so this patch just diagnoses taking address of a member function when not in immediate context.
Bootstrapped/regtested on x86_64-linux and i686-linux (without go, that seem to have some evrp issue when building libgo on both), ok for trunk? 2021-10-18 Jakub Jelinek <ja...@redhat.com> PR c++/102753 * typeck.c (cp_build_addr_expr_1): Diagnose taking address of an immediate method. Use t instead of TREE_OPERAND (arg, 1). * g++.dg/cpp2a/consteval20.C: New test. --- gcc/cp/typeck.c.jj 2021-10-05 09:53:55.382734051 +0200 +++ gcc/cp/typeck.c 2021-10-15 19:28:38.034213437 +0200 @@ -6773,9 +6773,21 @@ cp_build_addr_expr_1 (tree arg, bool str return error_mark_node; } + if (TREE_CODE (t) == FUNCTION_DECL + && DECL_IMMEDIATE_FUNCTION_P (t) + && cp_unevaluated_operand == 0 + && (current_function_decl == NULL_TREE + || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))) + { + if (complain & tf_error) + error_at (loc, "taking address of an immediate function %qD", + t); + return error_mark_node; + } + type = build_ptrmem_type (context_for_name_lookup (t), TREE_TYPE (t)); - t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1)); + t = make_ptrmem_cst (type, t); return t; } --- gcc/testsuite/g++.dg/cpp2a/consteval20.C.jj 2021-10-15 19:40:38.691900472 +0200 +++ gcc/testsuite/g++.dg/cpp2a/consteval20.C 2021-10-15 19:49:15.281508419 +0200 @@ -0,0 +1,24 @@ +// PR c++/102753 +// { dg-do compile { target c++20 } } + +struct S { + consteval int foo () const { return 42; } +}; + +constexpr S s; + +int +bar () +{ + return (s.*&S::foo) (); // { dg-error "taking address of an immediate function" } +} + +constexpr auto a = &S::foo; // { dg-error "taking address of an immediate function" } + +consteval int +baz () +{ + return (s.*&S::foo) (); +} + +static_assert (baz () == 42); Jakub