On 12/12/24 3:28 PM, Patrick Palka wrote:
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk/14?

This fixes the testcase in the PR but doesn't thoroughly fix the
underlying issue since if we replace fnPtr with e.g. a constexpr variable
so that the callee is truly potentially constant then the ICE reappears
(due to encountering CAST_EXPR during constexpr evaluation from
maybe_warn_nodiscard), but with the previous patch this should now only
happen in checking mode.  I suspect a call to fold_non_dependent_expr is
missing, but I'm not sure where would be best to put it.

-- >8 --

We're incorrectly treating the templated callee (FnPtr)fnPtr, represented
as CAST_EXPR of TREE_LIST, as potentially constant here due to failing
to look through the TREE_LIST in the CAST_EXPR case of p_c_e_1.

        PR c++/117925

gcc/cp/ChangeLog:

        * constexpr.cc (potential_constant_expression_1) <case CAST_EXPR>:
        Fix check for class conversion to literal type to properly look
        through the TREE_LIST operand of a CAST_EXPR.

gcc/testsuite/ChangeLog:

        * g++.dg/template/non-dependent35.C: New test.
---
  gcc/cp/constexpr.cc                             | 11 ++++++++---
  gcc/testsuite/g++.dg/template/non-dependent35.C |  8 ++++++++
  2 files changed, 16 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/template/non-dependent35.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 221d57f6ffa..cda49008f81 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -10262,9 +10262,14 @@ potential_constant_expression_1 (tree t, bool 
want_rval, bool strict, bool now,
               && (dependent_type_p (TREE_TYPE (t))
                   || !COMPLETE_TYPE_P (TREE_TYPE (t))
                   || literal_type_p (TREE_TYPE (t)))
-              && TREE_OPERAND (t, 0))
-       {
-         tree type = TREE_TYPE (TREE_OPERAND (t, 0));
+              && TREE_OPERAND (t, 0)
+              && (TREE_CODE (t) != CAST_EXPR
+                  || !TREE_CHAIN (TREE_OPERAND (t, 0))))
+       {
+         tree from = TREE_OPERAND (t, 0);
+         if (TREE_CODE (t) == CAST_EXPR)
+           from = TREE_VALUE (from);
+         tree type = TREE_TYPE (from);

The cast handling seems to discount the possibility of a constexpr constructor for the cast-to type, which strikes me as an oversight.

But the patch is OK as is.

          /* If this is a dependent type, it could end up being a class
             with conversions.  */
          if (type == NULL_TREE || WILDCARD_TYPE_P (type))
diff --git a/gcc/testsuite/g++.dg/template/non-dependent35.C 
b/gcc/testsuite/g++.dg/template/non-dependent35.C
new file mode 100644
index 00000000000..7e3ba99b023
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/non-dependent35.C
@@ -0,0 +1,8 @@
+// PR c++/117925
+
+typedef int(*FnPtr)();
+
+template<class T>
+void fnICE(void* fnPtr) {
+  ((FnPtr)fnPtr)();
+}

Reply via email to