Message ID | 1516717664-896-1-git-send-email-dmalcolm@redhat.com |
---|---|
State | New |
Headers | show |
Series | C++: Fix ICE in fold_for_warn on CAST_EXPR (PR c++/83974) | expand |
On Tue, Jan 23, 2018 at 9:27 AM, David Malcolm <dmalcolm@redhat.com> wrote: > 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, Because they are template-only codes, that cxx_eval_constant_expression should never see. They shouldn't survive the call to instantiate_non_dependent_expr_internal from fold_non_dependent_expr. Jason
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; +};