On 10/18/21 04:12, Jakub Jelinek wrote:
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)))
This doesn't cover some of the other cases of immediate context; we
should probably factor most of immediate_invocation_p out into a
function called something like in_immediate_context and use it here, and
in several other places as well.
+ {
+ 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