PR c++/89217 - ICE with list-initialization in range-based for loop.
authorMarek Polacek <polacek@redhat.com>
Sun, 17 Feb 2019 16:52:40 +0000 (16:52 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Sun, 17 Feb 2019 16:52:40 +0000 (16:52 +0000)
* 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
gcc/cp/constexpr.c
gcc/cp/cp-tree.h
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/range-for37.C [new file with mode: 0644]

index d6d1f595f1ccae5e81f27f885ed442b22072589a..d4e062539aff4995cb6183d55a4caf7e8d6ae758 100644 (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.
index 923763faa0a03d57deb64de9ce63d2cb2314a207..d946a797999b7df31934a2aca962e4e32ce2c3e0 100644 (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);
index 44a3620a539fc09af9bb2dadb35ddc946993a21b..60ca1366cf63cf442112f3884a106a1bd200eb50 100644 (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);
index aa5a163dd64747dfce35ba9dbe46e0e7692bf452..3ecd192bced7b8667f2092dca4b6471aa62895e8 100644 (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;
index 45fbe7c0296ab34d52705c87989888bd3de17806..38959b3248d1a954261f785b3ad277bac7c34e88 100644 (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
diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for37.C b/gcc/testsuite/g++.dg/cpp0x/range-for37.C
new file mode 100644 (file)
index 0000000..d5c7c09
--- /dev/null
@@ -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}) {}
+    }
+};