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)))
              /* 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" 
}
+}
-- 
2.43.0.rc1

Reply via email to