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>
PR c++/89744 - ICE with specialization of member class template.
......
......@@ -5581,45 +5581,29 @@ clear_cv_and_fold_caches (void)
clear_fold_cache ();
}
/* 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. */
/* Internal function handling expressions in templates for
fold_non_dependent_expr and fold_non_dependent_init.
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 we're in a template, but T isn't value dependent, simplify
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. */
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))
{
processing_template_decl_sentinel s;
t = instantiate_non_dependent_expr_internal (t, complain);
if (type_unknown_p (t)
|| BRACE_ENCLOSED_INITIALIZER_P (t))
if (type_unknown_p (t) || BRACE_ENCLOSED_INITIALIZER_P (t))
{
if (TREE_OVERFLOW_P (t))
{
......@@ -5645,12 +5629,68 @@ fold_non_dependent_expr (tree 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
(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);
}
/* 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
than wrapped in a TARGET_EXPR.
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);
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;
......
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
......
// 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