From 1f6857ba5608f715621cfe8d3c3be31b3040e9e6 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Sun, 17 Feb 2019 16:52:40 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 9 ++++++ gcc/cp/constexpr.c | 2 +- gcc/cp/cp-tree.h | 1 + gcc/cp/semantics.c | 40 +++++++++++++++++++----- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/cpp0x/range-for37.C | 24 ++++++++++++++ 6 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/range-for37.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d6d1f595f1c..d4e062539af 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2019-02-17 Marek Polacek + + 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 PR c++/89297 - ICE with OVERLOAD in template. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 923763faa0a..d946a797999 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 44a3620a539..60ca1366cf6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7710,6 +7710,7 @@ extern void explain_invalid_constexpr_fn (tree); extern vec 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); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index aa5a163dd64..3ecd192bced 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 45fbe7c0296..38959b3248d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-02-17 Marek Polacek + + 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 PR c++/88680 diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for37.C b/gcc/testsuite/g++.dg/cpp0x/range-for37.C new file mode 100644 index 00000000000..d5c7c091d96 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/range-for37.C @@ -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(); } + R& r; + + template + void f2() + { + for (auto i : C{r}) {} + } +}; -- 2.30.2