PR c++/83974 reports an ICE within fold_for_warn when calling cxx_eval_constant_expression on a CAST_EXPR.
This comes from a pointer-to-member-function. The result of build_ptrmemfunc (within cp_convert_to_pointer for a null ptr) is a CONSTRUCTOR containing, amongst other things a CAST_EXPR of a TREE_LIST containing the zero INTEGER_CST. After r256804, fold_for_warn within a template calls fold_non_dependent_expr. For this tree, is_nondependent_constant_expression returns true. potential_constant_expression_1 has these cases: case TREE_LIST: { gcc_assert (TREE_PURPOSE (t) == NULL_TREE || DECL_P (TREE_PURPOSE (t))); if (!RECUR (TREE_VALUE (t), want_rval)) return false; if (TREE_CHAIN (t) == NULL_TREE) return true; return RECUR (TREE_CHAIN (t), want_rval); } and: case CAST_EXPR: case CONST_CAST_EXPR: case STATIC_CAST_EXPR: case REINTERPRET_CAST_EXPR: case IMPLICIT_CONV_EXPR: if (cxx_dialect < cxx11 && !dependent_type_p (TREE_TYPE (t)) && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))) /* In C++98, a conversion to non-integral type can't be part of a constant expression. */ { // reject it } // accept it and thus returns true for the CAST_EXPR and TREE_LIST, and hence for the CONSTRUCTOR as a whole. However, cxx_eval_constant_expression does not support these tree codes, ICEing in the default case with: internal_error ("unexpected expression %qE of kind %s", t, It seems that, given potential_constant_expression_1 can return true for these cases, then cxx_eval_constant_expression ought to handle them, which this patch implements, fixing the ICE. Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. OK for trunk? gcc/cp/ChangeLog: PR c++/83974 * constexpr.c (cxx_eval_constant_expression): Handle case TREE_LIST. Handle CAST_EXPR, CONST_CAST_EXPR, STATIC_CAST_EXPR, REINTERPRET_CAST_EXPR and IMPLICIT_CONV_EXPR via cxx_eval_unary_expression. gcc/testsuite/ChangeLog: PR c++/83974 * g++.dg/warn/pr83974.C: New test case. --- gcc/cp/constexpr.c | 27 +++++++++++++++++++++++++++ gcc/testsuite/g++.dg/warn/pr83974.C | 11 +++++++++++ 2 files changed, 38 insertions(+) create mode 100644 gcc/testsuite/g++.dg/warn/pr83974.C diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index ca7f369..a593132 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -4348,6 +4348,24 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, } break; + case TREE_LIST: + { + tree value, chain; + gcc_assert (TREE_PURPOSE (t) == NULL_TREE + || DECL_P (TREE_PURPOSE (t))); + value = cxx_eval_constant_expression (ctx, TREE_VALUE (t), lval, + non_constant_p, overflow_p, + jump_target); + if (TREE_CHAIN (t)) + chain = cxx_eval_constant_expression (ctx, TREE_CHAIN (t), lval, + non_constant_p, overflow_p, + jump_target); + else + chain = NULL_TREE; + r = tree_cons (TREE_PURPOSE (t), value, chain); + } + break; + case POINTER_PLUS_EXPR: case POINTER_DIFF_EXPR: case PLUS_EXPR: @@ -4594,6 +4612,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, return cxx_eval_statement_list (&new_ctx, t, non_constant_p, overflow_p, jump_target); + case CAST_EXPR: + case CONST_CAST_EXPR: + case STATIC_CAST_EXPR: + case REINTERPRET_CAST_EXPR: + case IMPLICIT_CONV_EXPR: + r = cxx_eval_unary_expression (ctx, t, lval, + non_constant_p, overflow_p); + break; + case BIND_EXPR: return cxx_eval_constant_expression (ctx, BIND_EXPR_BODY (t), lval, diff --git a/gcc/testsuite/g++.dg/warn/pr83974.C b/gcc/testsuite/g++.dg/warn/pr83974.C new file mode 100644 index 0000000..af12c2d --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/pr83974.C @@ -0,0 +1,11 @@ +// { dg-options "-Wtautological-compare" } + +struct A { + typedef void (A::*B) (); + operator B (); +}; +template <typename> +struct C { + void foo () { d == 0; } + A d; +}; -- 1.8.5.3