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)();
+}