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
This commit is contained in:
parent
93755deb5c
commit
a81c8e8c9a
|
@ -1,3 +1,14 @@
|
|||
2019-03-31 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
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 <jason@redhat.com>
|
||||
|
||||
PR c++/89744 - ICE with specialization of member class template.
|
||||
|
|
|
@ -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 <typename T> void f(T[1 + 1]);
|
||||
template <typename T> 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 <typename T> void f(T[1 + 1]);
|
||||
template <typename T> void f(T[2]);
|
||||
return maybe_constant_value (t, NULL_TREE, manifestly_const_eval);
|
||||
}
|
||||
|
||||
|
||||
/* Like maybe_constant_init but first fully instantiate the argument. */
|
||||
|
||||
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;
|
||||
|
||||
as two declarations of the same function, for example. */
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (is_nondependent_constant_expression (t))
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2019-03-31 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/89852 - ICE with C++11 functional cast with { }.
|
||||
* g++.dg/cpp0x/initlist115.C: New test.
|
||||
|
||||
2019-03-31 Harald Anlauf <anlauf@gmx.de>
|
||||
|
||||
PR fortran/83515
|
||||
|
|
|
@ -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 <typename>
|
||||
void k()
|
||||
{
|
||||
B{j};
|
||||
}
|
Loading…
Reference in New Issue