PR c++/69261
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Jan 2016 15:32:31 +0000 (15:32 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 14 Jan 2016 15:32:31 +0000 (15:32 +0000)
* constexpr.c (find_array_ctor_elt): Handle splitting RANGE_EXPR.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@232370 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp1y/constexpr-array2.C [new file with mode: 0644]

index 7230c71..54db540 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-14  Jason Merrill  <jason@redhat.com>
+
+       PR c++/69261
+       * constexpr.c (find_array_ctor_elt): Handle splitting RANGE_EXPR.
+
 2016-01-12  Marek Polacek  <polacek@redhat.com>
 
        PR c++/68979
index 36a1e42..6ab4696 100644 (file)
@@ -1725,14 +1725,57 @@ find_array_ctor_elt (tree ary, tree dindex, bool insert = false)
   while (begin != end)
     {
       unsigned HOST_WIDE_INT middle = (begin + end) / 2;
+      constructor_elt &elt = (*elts)[middle];
+      tree idx = elt.index;
 
-      int cmp = array_index_cmp (dindex, (*elts)[middle].index);
+      int cmp = array_index_cmp (dindex, idx);
       if (cmp < 0)
        end = middle;
       else if (cmp > 0)
        begin = middle + 1;
       else
-       return middle;
+       {
+         if (insert && TREE_CODE (idx) == RANGE_EXPR)
+           {
+             /* We need to split the range.  */
+             constructor_elt e;
+             tree lo = TREE_OPERAND (idx, 0);
+             tree hi = TREE_OPERAND (idx, 1);
+             if (tree_int_cst_lt (lo, dindex))
+               {
+                 /* There are still some lower elts; shorten the range.  */
+                 tree new_hi = int_const_binop (MINUS_EXPR, dindex,
+                                                size_one_node);
+                 if (tree_int_cst_equal (lo, new_hi))
+                   /* Only one element left, no longer a range.  */
+                   elt.index = lo;
+                 else
+                   TREE_OPERAND (idx, 1) = new_hi;
+                 /* Append the element we want to insert.  */
+                 ++middle;
+                 e.index = dindex;
+                 e.value = unshare_expr (elt.value);
+                 vec_safe_insert (CONSTRUCTOR_ELTS (ary), middle, e);
+               }
+             else
+               /* No lower elts, the range elt is now ours.  */
+               elt.index = dindex;
+
+             if (tree_int_cst_lt (dindex, hi))
+               {
+                 /* There are still some higher elts; append a range.  */
+                 tree new_lo = int_const_binop (PLUS_EXPR, dindex,
+                                                size_one_node);
+                 if (tree_int_cst_equal (new_lo, hi))
+                   e.index = hi;
+                 else
+                   e.index = build2 (RANGE_EXPR, sizetype, new_lo, hi);
+                 e.value = unshare_expr (elt.value);
+                 vec_safe_insert (CONSTRUCTOR_ELTS (ary), middle+1, e);
+               }
+           }
+         return middle;
+       }
     }
 
   if (insert)
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-array2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-array2.C
new file mode 100644 (file)
index 0000000..71b3642
--- /dev/null
@@ -0,0 +1,63 @@
+// PR c++/69261
+// { dg-do run { target c++14 } }
+
+typedef __SIZE_TYPE__ size_t;
+
+template <size_t N>
+struct S
+{
+  constexpr S() = default;
+
+  template<size_t M>
+  constexpr S (char const (&d)[M]) : data { 0 }
+  {
+    static_assert (M <= N, "size!");
+    for (size_t i = 0; i != M; i++)
+      data[i] = d[i];
+  }
+  char data[N];
+};
+
+template <int N>
+constexpr S<N>
+s (char const (&d)[N])
+{
+  S<N> c {};
+  for (size_t i = 0; i != N; i++)
+    c.data[i] = d[i];
+  return c;
+}
+
+template <size_t N, size_t M>
+constexpr auto
+concat (S<N> const& s1, S<M> const& s2)
+{
+  S<N+M-1> s (s1.data);
+  for (size_t i = 0; i != M; i++)
+    s.data[N + i - 1] = s2.data[i];
+  return s;
+}
+
+template <size_t N, size_t M>
+constexpr auto
+concat (char const (&x)[N], char const (&y)[M])
+{
+  S<N+M-1> tmp { x };
+  for (size_t i = 0; i != M; i++)
+    tmp.data[N+i-1] = y[i];
+  return tmp;
+}
+
+int
+main ()
+{
+  auto constexpr s1 = s ("bla");
+  auto constexpr s2 = s ("blub");
+  S<8> constexpr s1s2 = concat (s1, s2);
+  auto constexpr c = concat ("bla", "blub");
+  if (__builtin_strcmp (s1.data, "bla")
+      || __builtin_strcmp (s2.data, "blub")
+      || __builtin_strcmp (s1s2.data, "blablub")
+      || __builtin_strcmp (c.data, "blablub"))
+    __builtin_abort ();
+}