PR c++/89217 - ICE with list-initialization in range-based for loop.

* constexpr.c (unshare_constructor): No longer static.
	* cp-tree.h (unshare_constructor): Declare.
	* semantics.c (finish_compound_literal): When dealing with a
	non-dependent expression in a template, return the original
	expression.  Pass LOOKUP_NO_NARROWING to digest_init_flags.

	* g++.dg/cpp0x/range-for37.C: New test.

From-SVN: r268969
This commit is contained in:
Marek Polacek 2019-02-17 16:52:40 +00:00 committed by Marek Polacek
parent b43e6340c8
commit 1f6857ba56
6 changed files with 72 additions and 9 deletions

View File

@ -1,3 +1,12 @@
2019-02-17 Marek Polacek <polacek@redhat.com>
PR c++/89217 - ICE with list-initialization in range-based for loop.
* constexpr.c (unshare_constructor): No longer static.
* cp-tree.h (unshare_constructor): Declare.
* semantics.c (finish_compound_literal): When dealing with a
non-dependent expression in a template, return the original
expression. Pass LOOKUP_NO_NARROWING to digest_init_flags.
2019-02-13 Marek Polacek <polacek@redhat.com>
PR c++/89297 - ICE with OVERLOAD in template.

View File

@ -1318,7 +1318,7 @@ find_constructor (tree *tp, int *walk_subtrees, void *)
/* If T is a CONSTRUCTOR or an expression that has a CONSTRUCTOR node as a
subexpression, return an unshared copy of T. Otherwise return T. */
static tree
tree
unshare_constructor (tree t)
{
tree ctor = walk_tree (&t, find_constructor, NULL, NULL);

View File

@ -7710,6 +7710,7 @@ extern void explain_invalid_constexpr_fn (tree);
extern vec<tree> cx_error_context (void);
extern tree fold_sizeof_expr (tree);
extern void clear_cv_and_fold_caches (void);
extern tree unshare_constructor (tree);
/* In cp-ubsan.c */
extern void cp_ubsan_maybe_instrument_member_call (tree);

View File

@ -2796,17 +2796,31 @@ finish_compound_literal (tree type, tree compound_literal,
return error_mark_node;
}
if (instantiation_dependent_expression_p (compound_literal)
|| dependent_type_p (type))
/* Used to hold a copy of the compound literal in a template. */
tree orig_cl = NULL_TREE;
if (processing_template_decl)
{
TREE_TYPE (compound_literal) = type;
const bool dependent_p
= (instantiation_dependent_expression_p (compound_literal)
|| dependent_type_p (type));
if (dependent_p)
/* We're about to return, no need to copy. */
orig_cl = compound_literal;
else
/* We're going to need a copy. */
orig_cl = unshare_constructor (compound_literal);
TREE_TYPE (orig_cl) = type;
/* Mark the expression as a compound literal. */
TREE_HAS_CONSTRUCTOR (compound_literal) = 1;
TREE_HAS_CONSTRUCTOR (orig_cl) = 1;
/* And as instantiation-dependent. */
CONSTRUCTOR_IS_DEPENDENT (compound_literal) = true;
CONSTRUCTOR_IS_DEPENDENT (orig_cl) = dependent_p;
if (fcl_context == fcl_c99)
CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1;
return compound_literal;
CONSTRUCTOR_C99_COMPOUND_LITERAL (orig_cl) = 1;
/* If the compound literal is dependent, we're done for now. */
if (dependent_p)
return orig_cl;
/* Otherwise, do go on to e.g. check narrowing. */
}
type = complete_type (type);
@ -2842,8 +2856,18 @@ finish_compound_literal (tree type, tree compound_literal,
if (type == error_mark_node)
return error_mark_node;
}
compound_literal = digest_init_flags (type, compound_literal, LOOKUP_NORMAL,
compound_literal = digest_init_flags (type, compound_literal,
LOOKUP_NORMAL | LOOKUP_NO_NARROWING,
complain);
/* If we're in a template, return the original compound literal. */
if (orig_cl)
{
if (!VECTOR_TYPE_P (type))
return get_target_expr_sfinae (orig_cl, complain);
else
return orig_cl;
}
if (TREE_CODE (compound_literal) == CONSTRUCTOR)
{
TREE_HAS_CONSTRUCTOR (compound_literal) = true;

View File

@ -1,3 +1,8 @@
2019-02-17 Marek Polacek <polacek@redhat.com>
PR c++/89217 - ICE with list-initialization in range-based for loop.
* g++.dg/cpp0x/range-for37.C: New test.
2019-02-16 David Malcolm <dmalcolm@redhat.com>
PR c++/88680

View File

@ -0,0 +1,24 @@
// PR c++/89217
// { dg-do compile { target c++11 } }
struct R {};
struct C
{
R* begin() const { return &r; }
R* end() const { return &r; }
R& r;
};
struct S
{
void f1() { f2<true>(); }
R& r;
template<bool>
void f2()
{
for (auto i : C{r}) {}
}
};