diff mbox series

c++: Diagnose taking address of an immediate member function [PR102753]

Message ID 20211018081258.GV304296@tucnak
State New
Headers show
Series c++: Diagnose taking address of an immediate member function [PR102753] | expand

Commit Message

Jakub Jelinek Oct. 18, 2021, 8:12 a.m. UTC
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  <jakub@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.


	Jakub

Comments

Jason Merrill Oct. 18, 2021, 4:42 p.m. UTC | #1
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  <jakub@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
>
diff mbox series

Patch

--- 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);