re PR c++/82218 ([C++1x] constexpr on static member function causes segfault)
authorPaolo Carlini <paolo.carlini@oracle.com>
Fri, 27 Oct 2017 23:14:43 +0000 (23:14 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Fri, 27 Oct 2017 23:14:43 +0000 (23:14 +0000)
2017-10-27  Paolo Carlini  <paolo.carlini@oracle.com>

PR c++/82218
* g++.dg/cpp1y/constexpr-82218.C: New.

From-SVN: r254189

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

index 58da3bb..7a90a8d 100644 (file)
@@ -1,3 +1,8 @@
+2017-10-27  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       PR c++/82218
+       * g++.dg/cpp1y/constexpr-82218.C: New.
+
 2017-10-27  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/opt68.ad[sb]: New test.
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-82218.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-82218.C
new file mode 100644 (file)
index 0000000..06507a9
--- /dev/null
@@ -0,0 +1,128 @@
+// PR c++/82218
+// { dg-do compile { target c++14 } }
+
+template<typename _Tp>
+struct identity
+{
+  typedef _Tp type;
+};
+
+template<typename _Tp>
+inline _Tp&&
+forward(typename identity<_Tp>::type&& __t)
+{ return __t; }
+
+template < typename T >
+class delegate;
+
+template < typename R, typename... Params >
+class delegate< R(Params...) > final
+{
+private:
+  using CallbackType = R (*)(void*, Params...);
+
+  using FunctionPtr = R (*)(Params...);
+
+  template < typename Object >
+  using MethodPtr = R (Object::*)(Params...);
+
+  template < typename Object >
+  using ConstMethodPtr = R (Object::*)(Params...) const;
+
+  void* obj_;
+  CallbackType cb_;
+
+  template < typename Object, MethodPtr< Object > Mptr >
+  constexpr static R invoke_method(void* obj, Params... params) noexcept(
+      noexcept((static_cast< Object* >(obj)->*Mptr)(params...)))
+  {
+    return (static_cast< Object* >(obj)->*Mptr)(params...);
+  }
+
+  template < typename Object, ConstMethodPtr< Object > Mptr >
+  constexpr static R invoke_method(void* obj, Params... params) noexcept(
+      noexcept((static_cast< Object* >(obj)->*Mptr)(params...)))
+  {
+    return (static_cast< Object* >(obj)->*Mptr)(params...);
+  }
+
+  template < FunctionPtr Fptr >
+  constexpr static R invoke_function(void*, Params... params) noexcept(
+      noexcept((*Fptr)(params...)))
+  {
+    return (*Fptr)(params...);
+  }
+
+  constexpr delegate(void* obj, CallbackType callback) noexcept : obj_(obj),
+                                                                  cb_(callback)
+  {
+  }
+
+  constexpr static R error_function(Params...)
+  {
+    while(1);
+  }
+
+public:
+  using base_type = delegate< R(Params...) >;
+
+  delegate()
+  {
+    *this = from< error_function >();
+  }
+
+  delegate(const base_type&) = default;
+  delegate(base_type&&)      = default;
+
+  base_type& operator=(const base_type&)  = default;
+  base_type& operator=(base_type&&)       = default;
+
+  template < typename Object, MethodPtr< Object > Mptr >
+  constexpr static auto from(Object& obj) noexcept
+  {
+    return delegate(&obj, &invoke_method< Object, Mptr >);
+  }
+
+  template < typename Object, ConstMethodPtr< Object > Mptr >
+  constexpr static auto from(Object& obj) noexcept
+  {
+    return delegate(&obj, &invoke_method< Object, Mptr >);
+  }
+
+  template < FunctionPtr Fptr >
+  constexpr static auto from() noexcept
+  {
+    static_assert(Fptr != nullptr, "Function pointer must not be null");
+
+    return delegate(nullptr, &invoke_function< Fptr >);
+  }
+
+  template < typename... Args >
+  constexpr auto operator()(Args&&... params) const
+      noexcept(noexcept((*cb_)(obj_, forward< Args >(params)...)))
+  {
+    return (*cb_)(obj_, forward< Args >(params)...);
+  }
+
+  constexpr bool valid() const noexcept
+  {
+    return (cb_ != &invoke_function< error_function >);
+  }
+
+  constexpr bool operator==(const delegate& other) const noexcept
+  {
+    return (obj_ == other.obj_) && (cb_ == other.cb_);
+  }
+
+  constexpr bool operator!=(const delegate& other) const noexcept
+  {
+    return (obj_ != other.obj_) || (cb_ != other.cb_);
+  }
+};
+
+delegate< void(void) > a;
+
+void test()
+{
+  a();
+}