On Mon, Jan 22, 2018 at 09:40:50AM -0500, Jason Merrill wrote:
> This seems like a workaround rather than a fix; we should fix
> split_nonconstant_init to work properly rather than override it.
> Specifically, it seems odd to return true if num_elts is 0; we
> shouldn't override DECL_INITIAL if we didn't actually split anything
> out.

Ah, ok, here's a patch for that, then.  Thanks.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2018-01-22  Marek Polacek  <pola...@redhat.com>

        PR c++/81933
        * typeck2.c (split_nonconstant_init_1): Return false if we didn't
        split out anything.
        
        * g++.dg/cpp1y/constexpr-empty4.C: New test.

diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c
index 8d933257f5f..8cb0e8811d3 100644
--- gcc/cp/typeck2.c
+++ gcc/cp/typeck2.c
@@ -725,6 +725,11 @@ split_nonconstant_init_1 (tree dest, tree init)
 
   /* The rest of the initializer is now a constant. */
   TREE_CONSTANT (init) = 1;
+
+  /* We didn't split out anything.  */
+  if (num_split_elts == 0)
+    return false;
+
   return complete_p && complete_ctor_at_level_p (TREE_TYPE (init),
                                                 num_split_elts, inner_type);
 }
diff --git gcc/testsuite/g++.dg/cpp1y/constexpr-empty4.C 
gcc/testsuite/g++.dg/cpp1y/constexpr-empty4.C
index e69de29bb2d..059220f8268 100644
--- gcc/testsuite/g++.dg/cpp1y/constexpr-empty4.C
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-empty4.C
@@ -0,0 +1,51 @@
+// PR c++/81933
+// { dg-do compile { target c++14 } }
+
+namespace std {
+template <typename _Tp> struct __decay_and_strip { typedef _Tp __type; };
+template <int> struct enable_if { typedef int type; };
+template <typename _Head> struct _Head_base {
+  constexpr _Head_base(_Head) {}
+};
+template <unsigned long, typename...> struct _Tuple_impl;
+template <unsigned long _Idx, typename _Head, typename... _Tail>
+struct _Tuple_impl<_Idx, _Head, _Tail...> : _Tuple_impl<1, _Tail...>, // { 
dg-warning "direct base" }
+                                            _Head_base<_Head> {
+  typedef _Tuple_impl<1, _Tail...> _Inherited;
+  typedef _Head_base<_Head> _Base;
+  constexpr _Tuple_impl(_Head __head, _Tail... __tail)
+      : _Inherited(__tail...), _Base(__head) {}
+  _Tuple_impl(const _Tuple_impl &) = default;
+  _Tuple_impl(_Tuple_impl &&);
+};
+template <unsigned long _Idx, typename _Head>
+struct _Tuple_impl<_Idx, _Head> : _Head_base<_Head> {
+  typedef _Head_base<_Head> _Base;
+  constexpr _Tuple_impl(_Head __head) : _Base(__head) {}
+};
+template <int> struct _TC {
+  static constexpr bool _NotSameTuple() { return true; }
+};
+template <typename... _Elements> class tuple : _Tuple_impl<0, _Elements...> {
+  typedef _Tuple_impl<0, _Elements...> _Inherited;
+
+public:
+  template <typename... _UElements,
+            enable_if<_TC<1>::_NotSameTuple()>::type = false>
+  constexpr tuple(_UElements... __elements) : _Inherited(__elements...) {}
+  tuple(const tuple &) = default;
+};
+template <typename... _Elements>
+constexpr tuple<typename __decay_and_strip<_Elements>::__type...>
+    make_tuple(_Elements... __args) {
+  typedef tuple<typename __decay_and_strip<_Elements>::__type...> 
__result_type;
+  return __result_type(__args...);
+}
+}
+struct any_udt {};
+template <typename... Tuples> constexpr auto flatten(Tuples... tuples) {
+  auto all = std::make_tuple(tuples...);
+  auto flat(all);
+  return flat;
+}
+constexpr auto fail = flatten(any_udt{}, any_udt{});

        Marek

Reply via email to