Message ID | 1516730781-54059-1-git-send-email-dmalcolm@redhat.com |
---|---|
State | New |
Headers | show |
Series | [v2] C++: Fix ICE in fold_for_warn on CAST_EXPR (PR c++/83974) | expand |
On Tue, Jan 23, 2018 at 1:06 PM, David Malcolm <dmalcolm@redhat.com> wrote: > On Tue, 2018-01-23 at 09:54 -0500, Jason Merrill wrote: >> 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 > > Aha - thanks. > > instantiate_non_dependent_expr_internal calls tsubst_copy_and_build, and > tsubst_copy_and_build is bailing out here: > > 18103 /* digest_init will do the wrong thing if we let it. */ > 18104 if (type && TYPE_PTRMEMFUNC_P (type)) > 18105 RETURN (t); > > leaving the CONSTRUCTOR uncopied, and thus containing the CAST_EXPR and > TREE_LIST, leading to the ICE within cxx_eval_constant_expression. Wow, how has that not broken things before now? The patch is OK. Jason
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 0296845..0e48a13 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18100,10 +18100,6 @@ tsubst_copy_and_build (tree t, if (type == error_mark_node) RETURN (error_mark_node); - /* digest_init will do the wrong thing if we let it. */ - if (type && TYPE_PTRMEMFUNC_P (type)) - RETURN (t); - /* We do not want to process the index of aggregate initializers as they are identifier nodes which will be looked up by digest_init. */ 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; +};