From a81c8e8c9ac60b0ba255d4082d65eab546eec3ec Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Sun, 31 Mar 2019 20:37:22 +0000 Subject: [PATCH] PR c++/89852 - ICE with C++11 functional cast with { }. * constexpr.c (fold_non_dependent_expr_template): New static function broken out of... (fold_non_dependent_expr): ...here. (fold_non_dependent_init): New function. * cp-tree.h (fold_non_dependent_init): Declare. * typeck2.c (massage_init_elt): Call fold_non_dependent_init instead of fold_non_dependent_expr. Don't call maybe_constant_init. * g++.dg/cpp0x/initlist115.C: New test. From-SVN: r270048 --- gcc/cp/ChangeLog | 11 +++ gcc/cp/constexpr.c | 112 +++++++++++++++-------- gcc/cp/cp-tree.h | 3 + gcc/cp/typeck2.c | 3 +- gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/cpp0x/initlist115.C | 18 ++++ 6 files changed, 114 insertions(+), 38 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist115.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8a5e9209b34..8c6e9931db1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2019-03-31 Marek Polacek + + PR c++/89852 - ICE with C++11 functional cast with { }. + * constexpr.c (fold_non_dependent_expr_template): New static function + broken out of... + (fold_non_dependent_expr): ...here. + (fold_non_dependent_init): New function. + * cp-tree.h (fold_non_dependent_init): Declare. + * typeck2.c (massage_init_elt): Call fold_non_dependent_init instead + of fold_non_dependent_expr. Don't call maybe_constant_init. + 2019-03-30 Jason Merrill PR c++/89744 - ICE with specialization of member class template. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index daf34e10784..53854a8acd4 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5581,6 +5581,58 @@ clear_cv_and_fold_caches (void) clear_fold_cache (); } +/* Internal function handling expressions in templates for + fold_non_dependent_expr and fold_non_dependent_init. + + If we're in a template, but T isn't value dependent, simplify + it. We're supposed to treat: + + template void f(T[1 + 1]); + template void f(T[2]); + + as two declarations of the same function, for example. */ + +static tree +fold_non_dependent_expr_template (tree t, tsubst_flags_t complain, + bool manifestly_const_eval) +{ + gcc_assert (processing_template_decl); + + if (is_nondependent_constant_expression (t)) + { + processing_template_decl_sentinel s; + t = instantiate_non_dependent_expr_internal (t, complain); + + if (type_unknown_p (t) || BRACE_ENCLOSED_INITIALIZER_P (t)) + { + if (TREE_OVERFLOW_P (t)) + { + t = build_nop (TREE_TYPE (t), t); + TREE_CONSTANT (t) = false; + } + return t; + } + + tree r = cxx_eval_outermost_constant_expr (t, true, true, + manifestly_const_eval, + NULL_TREE); + /* cp_tree_equal looks through NOPs, so allow them. */ + gcc_checking_assert (r == t + || CONVERT_EXPR_P (t) + || TREE_CODE (t) == VIEW_CONVERT_EXPR + || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) + || !cp_tree_equal (r, t)); + return r; + } + else if (TREE_OVERFLOW_P (t)) + { + t = build_nop (TREE_TYPE (t), t); + TREE_CONSTANT (t) = false; + } + + return t; +} + /* Like maybe_constant_value but first fully instantiate the argument. Note: this is equivalent to instantiate_non_dependent_expr_sfinae @@ -5604,51 +5656,39 @@ fold_non_dependent_expr (tree t, if (t == NULL_TREE) return NULL_TREE; - /* If we're in a template, but T isn't value dependent, simplify - it. We're supposed to treat: + if (processing_template_decl) + return fold_non_dependent_expr_template (t, complain, + manifestly_const_eval); - template void f(T[1 + 1]); - template void f(T[2]); + return maybe_constant_value (t, NULL_TREE, manifestly_const_eval); +} - as two declarations of the same function, for example. */ - if (processing_template_decl) - { - if (is_nondependent_constant_expression (t)) - { - processing_template_decl_sentinel s; - t = instantiate_non_dependent_expr_internal (t, complain); - if (type_unknown_p (t) - || BRACE_ENCLOSED_INITIALIZER_P (t)) - { - if (TREE_OVERFLOW_P (t)) - { - t = build_nop (TREE_TYPE (t), t); - TREE_CONSTANT (t) = false; - } - return t; - } +/* Like maybe_constant_init but first fully instantiate the argument. */ - tree r = cxx_eval_outermost_constant_expr (t, true, true, - manifestly_const_eval, - NULL_TREE); - /* cp_tree_equal looks through NOPs, so allow them. */ - gcc_checking_assert (r == t - || CONVERT_EXPR_P (t) - || TREE_CODE (t) == VIEW_CONVERT_EXPR - || (TREE_CONSTANT (t) && !TREE_CONSTANT (r)) - || !cp_tree_equal (r, t)); - return r; - } - else if (TREE_OVERFLOW_P (t)) +tree +fold_non_dependent_init (tree t, + tsubst_flags_t complain /*=tf_warning_or_error*/, + bool manifestly_const_eval /*=false*/) +{ + if (t == NULL_TREE) + return NULL_TREE; + + if (processing_template_decl) + { + t = fold_non_dependent_expr_template (t, complain, + manifestly_const_eval); + /* maybe_constant_init does this stripping, so do it here too. */ + if (TREE_CODE (t) == TARGET_EXPR) { - t = build_nop (TREE_TYPE (t), t); - TREE_CONSTANT (t) = false; + tree init = TARGET_EXPR_INITIAL (t); + if (TREE_CODE (init) == CONSTRUCTOR) + t = init; } return t; } - return maybe_constant_value (t, NULL_TREE, manifestly_const_eval); + return maybe_constant_init (t, NULL_TREE, manifestly_const_eval); } /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 59152753825..b87b968fa4e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7716,6 +7716,9 @@ extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false); extern tree fold_non_dependent_expr (tree, tsubst_flags_t = tf_warning_or_error, bool = false); +extern tree fold_non_dependent_init (tree, + tsubst_flags_t = tf_warning_or_error, + bool = false); extern tree fold_simple (tree); extern bool is_sub_constant_expr (tree); extern bool reduced_constant_expression_p (tree); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 7f242ba93da..fa98b1cb8b5 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1346,8 +1346,7 @@ massage_init_elt (tree type, tree init, int nested, int flags, init = TARGET_EXPR_INITIAL (init); /* When we defer constant folding within a statement, we may want to defer this folding as well. */ - tree t = fold_non_dependent_expr (init, complain); - t = maybe_constant_init (t); + tree t = fold_non_dependent_init (init, complain); if (TREE_CONSTANT (t)) init = t; return init; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3c173b5b726..deb903bdc69 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-03-31 Marek Polacek + + PR c++/89852 - ICE with C++11 functional cast with { }. + * g++.dg/cpp0x/initlist115.C: New test. + 2019-03-31 Harald Anlauf PR fortran/83515 diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist115.C b/gcc/testsuite/g++.dg/cpp0x/initlist115.C new file mode 100644 index 00000000000..ee4b6d4a870 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist115.C @@ -0,0 +1,18 @@ +// PR c++/89852 +// { dg-do compile { target c++11 } } + +struct A { + int b; +}; + +struct B { + A g; +}; + +const auto j = A{}; + +template +void k() +{ + B{j}; +} -- 2.30.2