aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/call.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-10-27 09:03:28 +0200
committerJakub Jelinek <jakub@redhat.com>2021-10-27 09:03:28 +0200
commit4b2fda8bea3fdcc9421726e5a21e537f745cad0b (patch)
treedba7b242d075d5589f704481cf1bbf5d4f325468 /gcc/cp/call.c
parent3ff5b4edbed4d7b31a88e748e482b01fb5428a8c (diff)
downloadgcc-4b2fda8bea3fdcc9421726e5a21e537f745cad0b.zip
gcc-4b2fda8bea3fdcc9421726e5a21e537f745cad0b.tar.gz
gcc-4b2fda8bea3fdcc9421726e5a21e537f745cad0b.tar.bz2
c++: Diagnose taking address of an immediate member function [PR102753]
The consteval20.C 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. On Mon, Oct 18, 2021 at 12:42:00PM -0400, Jason Merrill wrote: > > --- 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. You're right, I've done that for the two spots in cp_build_addr_expr_1 and added testsuite coverage for where it changed behavior. While doing that I've discovered further issues. One is that we weren't diagnosing PMFs referring to immediate methods returned from immediate functions (either directly or embedded in aggregates). I'm not sure if it can only appear as PTRMEM_CST which I've handled (cp_walk_subtree only walks the type and not the PTRMEM_CST_MEMBER) or something else. Another issue is that while default arg in immediate function containing &immediate_fn works properly, if it is immediate_fn instead, we were incorrectly rejecting it. I've handled this in build_over_call, though with this usage in_consteval_if_p is slightly misnamed, it stands for in consteval if or some other reason why we are currently in immediate function context. Though, that flag alone can't be all the reasons for being in immediate function contexts, as I've tried the other reasons can't be handled in such a bool and need to be tested too. 2021-10-27 Jakub Jelinek <jakub@redhat.com> PR c++/102753 * cp-tree.h (saved_scope): Document that consteval_if_p member is also set while processing immediate invocation. (in_immediate_context): Declare. * call.c (in_immediate_context): New function. (immediate_invocation_p): Use it. (struct in_consteval_if_p_temp_override): New class. (build_over_call): Temporarily set in_consteval_if_p for processing immediate invocation arguments. * typeck.c (cp_build_addr_expr_1): Diagnose taking address of an immediate method. Use t instead of TREE_OPERAND (arg, 1). Use in_immediate_context function. * constexpr.c (find_immediate_fndecl): Handle PTRMEM_CST which refers to immediate function decl. * g++.dg/cpp2a/consteval13.C: Don't expect errors. * g++.dg/cpp2a/consteval20.C: New test. * g++.dg/cpp2a/consteval21.C: New test. * g++.dg/cpp2a/consteval22.C: New test. * g++.dg/cpp2a/consteval23.C: New test. * g++.dg/cpp23/consteval-if11.C: New test.
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r--gcc/cp/call.c40
1 files changed, 34 insertions, 6 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c5601d9..20e66c6 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -9025,6 +9025,20 @@ build_trivial_dtor_call (tree instance, bool no_ptr_deref)
instance, clobber);
}
+/* Return true if in an immediate function context, or an unevaluated operand,
+ or a subexpression of an immediate invocation. */
+
+bool
+in_immediate_context ()
+{
+ return (cp_unevaluated_operand != 0
+ || (current_function_decl != NULL_TREE
+ && DECL_IMMEDIATE_FUNCTION_P (current_function_decl))
+ || (current_binding_level->kind == sk_function_parms
+ && current_binding_level->immediate_fn_ctx_p)
+ || in_consteval_if_p);
+}
+
/* Return true if a call to FN with number of arguments NARGS
is an immediate invocation. */
@@ -9033,18 +9047,25 @@ immediate_invocation_p (tree fn, int nargs)
{
return (TREE_CODE (fn) == FUNCTION_DECL
&& DECL_IMMEDIATE_FUNCTION_P (fn)
- && cp_unevaluated_operand == 0
- && (current_function_decl == NULL_TREE
- || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl))
- && (current_binding_level->kind != sk_function_parms
- || !current_binding_level->immediate_fn_ctx_p)
- && !in_consteval_if_p
+ && !in_immediate_context ()
/* As an exception, we defer std::source_location::current ()
invocations until genericization because LWG3396 mandates
special behavior for it. */
&& (nargs > 1 || !source_location_current_p (fn)));
}
+/* temp_override for in_consteval_if_p, which can't use make_temp_override
+ because it is a bitfield. */
+
+struct in_consteval_if_p_temp_override {
+ bool save_in_consteval_if_p;
+ in_consteval_if_p_temp_override ()
+ : save_in_consteval_if_p (in_consteval_if_p) {}
+ void reset () { in_consteval_if_p = save_in_consteval_if_p; }
+ ~in_consteval_if_p_temp_override ()
+ { reset (); }
+};
+
/* Subroutine of the various build_*_call functions. Overload resolution
has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
@@ -9254,6 +9275,12 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
nargs = parmlen;
argarray = XALLOCAVEC (tree, nargs);
+ in_consteval_if_p_temp_override icip;
+ /* If the call is immediate function invocation, make sure
+ taking address of immediate functions is allowed in its arguments. */
+ if (immediate_invocation_p (STRIP_TEMPLATE (fn), nargs))
+ in_consteval_if_p = true;
+
/* The implicit parameters to a constructor are not considered by overload
resolution, and must be of the proper type. */
if (DECL_CONSTRUCTOR_P (fn))
@@ -9498,6 +9525,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
gcc_assert (j <= nargs);
nargs = j;
+ icip.reset ();
/* Avoid performing argument transformation if warnings are disabled.
When tf_warning is set and at least one of the warnings is active