re PR c++/53202 (Copy constructor not called when starting a thread)
authorJason Merrill <jason@redhat.com>
Mon, 25 Jun 2012 15:17:59 +0000 (11:17 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 25 Jun 2012 15:17:59 +0000 (11:17 -0400)
PR c++/53202
* semantics.c (build_data_member_initialization): Always keep
initializer for empty base.
(cxx_eval_bare_aggregate): Discard it here.

From-SVN: r188940

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

index df3a9177b451220a251f63dfe747002180cee96c..f87b4d68ec14600a919ead358864f2179d0dc2ff 100644 (file)
@@ -1,5 +1,10 @@
 2012-06-25  Jason Merrill  <jason@redhat.com>
 
+       PR c++/53202
+       * semantics.c (build_data_member_initialization): Always keep
+       initializer for empty base.
+       (cxx_eval_bare_aggregate): Discard it here.
+
        PR c++/53565
        * pt.c (tsubst_omp_for_iterator): Simplify DECL_EXPR handling.
        (tsubst_expr) [OMP_FOR]: Here, too.
index ee418616992f7d8ee616c031919585db02a93e34..2d64a6671e4d7ef220ab648f815c46be8856d8ca 100644 (file)
@@ -5838,12 +5838,9 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec)
        member = op;
       else
        {
-         /* We don't put out anything for an empty base.  */
+         /* This is an initializer for an empty base; keep it for now so
+            we can check it in cxx_eval_bare_aggregate.  */
          gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member))));
-         /* But if the initializer isn't constexpr, leave it in so we
-            complain later.  */
-         if (potential_constant_expression (init))
-           return true;
        }
     }
   if (TREE_CODE (member) == ADDR_EXPR)
@@ -7064,6 +7061,12 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
          constructor_elt *inner = base_field_constructor_elt (n, ce->index);
          inner->value = elt;
        }
+      else if (TREE_CODE (ce->index) == NOP_EXPR)
+       {
+         /* This is an initializer for an empty base; now that we've
+            checked that it's constant, we can ignore it.  */
+         gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (ce->index))));
+       }
       else
        CONSTRUCTOR_APPEND_ELT (n, ce->index, elt);
     }
index 6fa762aac164a139aa07a59c0f83f55023227cbd..2f6f22e227ad5bc3612e288d16f02515926af793 100644 (file)
@@ -1,3 +1,8 @@
+2012-06-25  Jason Merrill  <jason@redhat.com>
+
+       PR c++/53202
+       * g++.dg/cpp0x/constexpr-tuple.C: New.
+
 2012-06-25  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/53759
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-tuple.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-tuple.C
new file mode 100644 (file)
index 0000000..f59cd84
--- /dev/null
@@ -0,0 +1,106 @@
+// PR c++/53202
+// { dg-do run { target c++11 } }
+
+#include <tuple>
+
+template<typename Callable>
+  struct Bind_simple
+  {
+    explicit
+    Bind_simple(const Callable& callable)
+    : _M_bound(callable)
+    { }
+
+    Bind_simple(const Bind_simple&) = default;
+    Bind_simple(Bind_simple&&) = default;
+
+    auto operator()() -> decltype((*(Callable*)0)())
+    {
+      return std::get<0>(_M_bound)();
+    }
+
+  private:
+
+    std::tuple<Callable> _M_bound;
+  };
+
+template<typename Callable>
+  Bind_simple<Callable>
+  bind_simple(Callable& callable)
+  {
+    return Bind_simple<Callable>(callable);
+  }
+
+struct thread
+{
+  struct ImplBase { };
+
+  template<typename T>
+    struct Impl : ImplBase {
+      T t;
+      Impl(T&& t) : t(std::move(t)) { }
+    };
+
+  template<typename T>
+    thread(T& t)
+    {
+      auto p = make_routine(bind_simple(t));
+
+      p->t();
+
+      delete p;
+    }
+
+  template<typename Callable>
+    Impl<Callable>*
+    make_routine(Callable&& f)
+    {
+      return new Impl<Callable>(std::forward<Callable>(f));
+    }
+};
+
+
+int c;
+class background_hello
+{
+public:
+    background_hello()
+    {
+      __builtin_printf("default ctor called, this=%p\n", this);
+      ++c;
+    }
+
+    background_hello(const background_hello &)
+    {
+      __builtin_printf("copy ctor called\n");
+      ++c;
+    }
+
+    background_hello(background_hello &&)
+    {
+      __builtin_printf("move ctor called\n");
+      ++c;
+    }
+
+    void operator ()() const
+    {
+      __builtin_printf("void background_hello::operator()() called, this=%p\n", this);
+    }
+
+    ~background_hello()
+    {
+      __builtin_printf("destructor called, this=%p\n", this);
+      --c;
+    }
+
+};
+
+int main()
+{
+  {
+    background_hello bh;
+    thread t(bh);
+  }
+  if (c != 0)
+    __builtin_abort ();
+}