aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2019-02-17 16:52:40 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2019-02-17 16:52:40 +0000
commit1f6857ba5608f715621cfe8d3c3be31b3040e9e6 (patch)
tree9dee916ca3c34d2ac5f7cf385af30f3daf880f59 /gcc
parentb43e6340c80f3ae0ddf70950a8f979f4791c3252 (diff)
downloadgcc-1f6857ba5608f715621cfe8d3c3be31b3040e9e6.zip
gcc-1f6857ba5608f715621cfe8d3c3be31b3040e9e6.tar.gz
gcc-1f6857ba5608f715621cfe8d3c3be31b3040e9e6.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/constexpr.c2
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/semantics.c40
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/range-for37.C24
6 files changed, 72 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d6d1f59..d4e0625 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 923763f..d946a79 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 44a3620..60ca136 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<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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index aa5a163..3ecd192 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 45fbe7c..38959b3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
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 0000000..d5c7c09
--- /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<true>(); }
+ R& r;
+
+ template<bool>
+ void f2()
+ {
+ for (auto i : C{r}) {}
+ }
+};