Commit a81c8e8c by Marek Polacek Committed by 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.

	* g++.dg/cpp0x/initlist115.C: New test.

From-SVN: r270048
parent 93755deb
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> 2019-03-30 Jason Merrill <jason@redhat.com>
PR c++/89744 - ICE with specialization of member class template. PR c++/89744 - ICE with specialization of member class template.
......
...@@ -5581,45 +5581,29 @@ clear_cv_and_fold_caches (void) ...@@ -5581,45 +5581,29 @@ clear_cv_and_fold_caches (void)
clear_fold_cache (); clear_fold_cache ();
} }
/* Like maybe_constant_value but first fully instantiate the argument. /* Internal function handling expressions in templates for
fold_non_dependent_expr and fold_non_dependent_init.
Note: this is equivalent to instantiate_non_dependent_expr_sfinae
(t, complain) followed by maybe_constant_value but is more efficient,
because it calls instantiation_dependent_expression_p and
potential_constant_expression at most once.
The manifestly_const_eval argument is passed to maybe_constant_value.
Callers should generally pass their active complain, or if they are in a
non-template, diagnosing context, they can use the default of
tf_warning_or_error. Callers that might be within a template context, don't
have a complain parameter, and aren't going to remember the result for long
(e.g. null_ptr_cst_p), can pass tf_none and deal with error_mark_node
appropriately. */
tree If we're in a template, but T isn't value dependent, simplify
fold_non_dependent_expr (tree t,
tsubst_flags_t complain /* = tf_warning_or_error */,
bool manifestly_const_eval /* = false */)
{
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: it. We're supposed to treat:
template <typename T> void f(T[1 + 1]); template <typename T> void f(T[1 + 1]);
template <typename T> void f(T[2]); template <typename T> void f(T[2]);
as two declarations of the same function, for example. */ as two declarations of the same function, for example. */
if (processing_template_decl)
{ 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)) if (is_nondependent_constant_expression (t))
{ {
processing_template_decl_sentinel s; processing_template_decl_sentinel s;
t = instantiate_non_dependent_expr_internal (t, complain); t = instantiate_non_dependent_expr_internal (t, complain);
if (type_unknown_p (t) if (type_unknown_p (t) || BRACE_ENCLOSED_INITIALIZER_P (t))
|| BRACE_ENCLOSED_INITIALIZER_P (t))
{ {
if (TREE_OVERFLOW_P (t)) if (TREE_OVERFLOW_P (t))
{ {
...@@ -5645,12 +5629,68 @@ fold_non_dependent_expr (tree t, ...@@ -5645,12 +5629,68 @@ fold_non_dependent_expr (tree t,
t = build_nop (TREE_TYPE (t), t); t = build_nop (TREE_TYPE (t), t);
TREE_CONSTANT (t) = false; TREE_CONSTANT (t) = false;
} }
return t; return t;
} }
/* Like maybe_constant_value but first fully instantiate the argument.
Note: this is equivalent to instantiate_non_dependent_expr_sfinae
(t, complain) followed by maybe_constant_value but is more efficient,
because it calls instantiation_dependent_expression_p and
potential_constant_expression at most once.
The manifestly_const_eval argument is passed to maybe_constant_value.
Callers should generally pass their active complain, or if they are in a
non-template, diagnosing context, they can use the default of
tf_warning_or_error. Callers that might be within a template context, don't
have a complain parameter, and aren't going to remember the result for long
(e.g. null_ptr_cst_p), can pass tf_none and deal with error_mark_node
appropriately. */
tree
fold_non_dependent_expr (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)
return fold_non_dependent_expr_template (t, complain,
manifestly_const_eval);
return maybe_constant_value (t, NULL_TREE, manifestly_const_eval); 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;
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)
{
tree init = TARGET_EXPR_INITIAL (t);
if (TREE_CODE (init) == CONSTRUCTOR)
t = init;
}
return t;
}
return maybe_constant_init (t, NULL_TREE, manifestly_const_eval);
}
/* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather
than wrapped in a TARGET_EXPR. than wrapped in a TARGET_EXPR.
ALLOW_NON_CONSTANT is false if T is required to be a constant expression. ALLOW_NON_CONSTANT is false if T is required to be a constant expression.
......
...@@ -7716,6 +7716,9 @@ extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false); ...@@ -7716,6 +7716,9 @@ extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
extern tree fold_non_dependent_expr (tree, extern tree fold_non_dependent_expr (tree,
tsubst_flags_t = tf_warning_or_error, tsubst_flags_t = tf_warning_or_error,
bool = false); bool = false);
extern tree fold_non_dependent_init (tree,
tsubst_flags_t = tf_warning_or_error,
bool = false);
extern tree fold_simple (tree); extern tree fold_simple (tree);
extern bool is_sub_constant_expr (tree); extern bool is_sub_constant_expr (tree);
extern bool reduced_constant_expression_p (tree); extern bool reduced_constant_expression_p (tree);
......
...@@ -1346,8 +1346,7 @@ massage_init_elt (tree type, tree init, int nested, int flags, ...@@ -1346,8 +1346,7 @@ massage_init_elt (tree type, tree init, int nested, int flags,
init = TARGET_EXPR_INITIAL (init); init = TARGET_EXPR_INITIAL (init);
/* When we defer constant folding within a statement, we may want to /* When we defer constant folding within a statement, we may want to
defer this folding as well. */ defer this folding as well. */
tree t = fold_non_dependent_expr (init, complain); tree t = fold_non_dependent_init (init, complain);
t = maybe_constant_init (t);
if (TREE_CONSTANT (t)) if (TREE_CONSTANT (t))
init = t; init = t;
return init; return init;
......
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> 2019-03-31 Harald Anlauf <anlauf@gmx.de>
PR fortran/83515 PR fortran/83515
......
// 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};
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment