diff mbox series

c++: constantness of call to function pointer [PR111703]

Message ID 20231115180350.2126787-1-ppalka@redhat.com
State New
Headers show
Series c++: constantness of call to function pointer [PR111703] | expand

Commit Message

Patrick Palka Nov. 15, 2023, 6:03 p.m. UTC
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
for trunk/13/12 (to match the PR107939 / r13-6525-ge09bc034d1b4d6 backports)?

-- >8 --

potential_constant_expression for a CALL_EXPR to a non-overload tests
FUNCTION_POINTER_TYPE_P on the callee rather than on the type of the
callee, which means we always pass want_rval=any when recursing and so
may fail to properly treat a non-constant function pointer callee as such.
Fixing this turns out to further work around the PR111703 issue.

	PR c++/111703
	PR c++/107939

gcc/cp/ChangeLog:

	* constexpr.cc (potential_constant_expression_1) <case CALL_EXPR>:
	Fix FUNCTION_POINTER_TYPE_P test.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/concepts-fn8.C: Extend test.
	* g++.dg/diagnostic/constexpr4.C: New test.
---
 gcc/cp/constexpr.cc                          | 4 +++-
 gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C    | 2 ++
 gcc/testsuite/g++.dg/diagnostic/constexpr4.C | 9 +++++++++
 3 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/diagnostic/constexpr4.C

Comments

Jason Merrill Nov. 15, 2023, 11:19 p.m. UTC | #1
On 11/15/23 13:03, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK
> for trunk/13/12 (to match the PR107939 / r13-6525-ge09bc034d1b4d6 backports)?
> 
> -- >8 --
> 
> potential_constant_expression for a CALL_EXPR to a non-overload tests
> FUNCTION_POINTER_TYPE_P on the callee rather than on the type of the
> callee, which means we always pass want_rval=any when recursing and so
> may fail to properly treat a non-constant function pointer callee as such.
> Fixing this turns out to further work around the PR111703 issue.
> 
> 	PR c++/111703
> 	PR c++/107939
> 
> gcc/cp/ChangeLog:
> 
> 	* constexpr.cc (potential_constant_expression_1) <case CALL_EXPR>:
> 	Fix FUNCTION_POINTER_TYPE_P test.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp2a/concepts-fn8.C: Extend test.
> 	* g++.dg/diagnostic/constexpr4.C: New test.
> ---
>   gcc/cp/constexpr.cc                          | 4 +++-
>   gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C    | 2 ++
>   gcc/testsuite/g++.dg/diagnostic/constexpr4.C | 9 +++++++++
>   3 files changed, 14 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/diagnostic/constexpr4.C
> 
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index 8a6b210144a..5ecc30117a1 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -9547,7 +9547,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
>   	  }
>   	else if (fun)
>             {
> -	    if (RECUR (fun, FUNCTION_POINTER_TYPE_P (fun) ? rval : any))
> +	    if (RECUR (fun, (TREE_TYPE (fun)
> +			     && FUNCTION_POINTER_TYPE_P (TREE_TYPE (fun))
> +			     ? rval : any)))

We might break this ?: out into a variable?  OK either way.

>   	      /* Might end up being a constant function pointer.  But it
>   		 could also be a function object with constexpr op(), so
>   		 we pass 'any' so that the underlying VAR_DECL is deemed
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C b/gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C
> index 3f63a5b28d7..c63d26c931d 100644
> --- a/gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C
> @@ -15,10 +15,12 @@ struct P {
>   };
>   
>   void (*f)(P);
> +P (*h)(P);
>   
>   template<class T>
>   constexpr bool g() {
>     P x;
>     f(x); // { dg-bogus "from here" }
> +  f(h(x)); // { dg-bogus "from here" }
>     return true;
>   }
> diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr4.C b/gcc/testsuite/g++.dg/diagnostic/constexpr4.C
> new file mode 100644
> index 00000000000..f971f533b08
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/diagnostic/constexpr4.C
> @@ -0,0 +1,9 @@
> +// Verify we diagnose a call to a non-constant function pointer ahead of time.
> +// { dg-do compile { target c++11 } }
> +
> +int (*f)(int);
> +
> +template<int N>
> +void g() {
> +  static_assert(f(N) == 0, ""); // { dg-error "non-constant|'f' is not usable" }
> +}
diff mbox series

Patch

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8a6b210144a..5ecc30117a1 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9547,7 +9547,9 @@  potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
 	  }
 	else if (fun)
           {
-	    if (RECUR (fun, FUNCTION_POINTER_TYPE_P (fun) ? rval : any))
+	    if (RECUR (fun, (TREE_TYPE (fun)
+			     && FUNCTION_POINTER_TYPE_P (TREE_TYPE (fun))
+			     ? rval : any)))
 	      /* Might end up being a constant function pointer.  But it
 		 could also be a function object with constexpr op(), so
 		 we pass 'any' so that the underlying VAR_DECL is deemed
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C b/gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C
index 3f63a5b28d7..c63d26c931d 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-fn8.C
@@ -15,10 +15,12 @@  struct P {
 };
 
 void (*f)(P);
+P (*h)(P);
 
 template<class T>
 constexpr bool g() {
   P x;
   f(x); // { dg-bogus "from here" }
+  f(h(x)); // { dg-bogus "from here" }
   return true;
 }
diff --git a/gcc/testsuite/g++.dg/diagnostic/constexpr4.C b/gcc/testsuite/g++.dg/diagnostic/constexpr4.C
new file mode 100644
index 00000000000..f971f533b08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/constexpr4.C
@@ -0,0 +1,9 @@ 
+// Verify we diagnose a call to a non-constant function pointer ahead of time.
+// { dg-do compile { target c++11 } }
+
+int (*f)(int);
+
+template<int N>
+void g() {
+  static_assert(f(N) == 0, ""); // { dg-error "non-constant|'f' is not usable" }
+}