[libcxx] r280775 - Fix PR30260 - optional<const T> not working.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 6 18:56:08 PDT 2016


Author: ericwf
Date: Tue Sep  6 20:56:07 2016
New Revision: 280775

URL: http://llvm.org/viewvc/llvm-project?rev=280775&view=rev
Log:
Fix PR30260 - optional<const T> not working.

This patch fixes PR30260 by using a (void*) cast on the placement argument
to placement new to casts away the const. See also http://llvm.org/PR30260.

As a drive by change this patch also changes the header guard for
<experimental/optional> to _LIBCPP_EXPERIMENTAL_OPTIONAL from _LIBCPP_OPTIONAL.

Modified:
    libcxx/trunk/include/experimental/optional
    libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp
    libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp
    libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp
    libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
    libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp
    libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp
    libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp
    libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp

Modified: libcxx/trunk/include/experimental/optional
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/experimental/optional?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/include/experimental/optional (original)
+++ libcxx/trunk/include/experimental/optional Tue Sep  6 20:56:07 2016
@@ -8,8 +8,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef _LIBCPP_OPTIONAL
-#define _LIBCPP_OPTIONAL
+#ifndef _LIBCPP_EXPERIMENTAL_OPTIONAL
+#define _LIBCPP_EXPERIMENTAL_OPTIONAL
 
 /*
     optional synopsis
@@ -211,7 +211,7 @@ protected:
         :  __engaged_(__x.__engaged_)
         {
             if (__engaged_)
-                ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
+                ::new((void*)_VSTD::addressof(__val_)) value_type(__x.__val_);
         }
 
     _LIBCPP_INLINE_VISIBILITY
@@ -220,7 +220,7 @@ protected:
         :  __engaged_(__x.__engaged_)
         {
             if (__engaged_)
-                ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
+                ::new((void*)_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
         }
 
     _LIBCPP_INLINE_VISIBILITY
@@ -262,7 +262,7 @@ protected:
         :  __engaged_(__x.__engaged_)
         {
             if (__engaged_)
-                ::new(_VSTD::addressof(__val_)) value_type(__x.__val_);
+                ::new((void*)_VSTD::addressof(__val_)) value_type(__x.__val_);
         }
 
     _LIBCPP_INLINE_VISIBILITY
@@ -271,7 +271,7 @@ protected:
         :  __engaged_(__x.__engaged_)
         {
             if (__engaged_)
-                ::new(_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
+                ::new((void*)_VSTD::addressof(__val_)) value_type(_VSTD::move(__x.__val_));
         }
 
     _LIBCPP_INLINE_VISIBILITY
@@ -368,7 +368,7 @@ public:
             if (this->__engaged_)
                 this->__val_.~value_type();
             else
-                ::new(_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
+                ::new((void*)_VSTD::addressof(this->__val_)) value_type(__opt.__val_);
             this->__engaged_ = __opt.__engaged_;
         }
         return *this;
@@ -390,7 +390,8 @@ public:
             if (this->__engaged_)
                 this->__val_.~value_type();
             else
-                ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
+                ::new((void*)_VSTD::addressof(this->__val_))
+                    value_type(_VSTD::move(__opt.__val_));
             this->__engaged_ = __opt.__engaged_;
         }
         return *this;
@@ -412,7 +413,7 @@ public:
             this->__val_ = _VSTD::forward<_Up>(__v);
         else
         {
-            ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
+            ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Up>(__v));
             this->__engaged_ = true;
         }
         return *this;
@@ -429,7 +430,8 @@ public:
     emplace(_Args&&... __args)
     {
         *this = nullopt;
-        ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
+        ::new((void*)_VSTD::addressof(this->__val_))
+            value_type(_VSTD::forward<_Args>(__args)...);
         this->__engaged_ = true;
     }
 
@@ -444,7 +446,8 @@ public:
     emplace(initializer_list<_Up> __il, _Args&&... __args)
     {
         *this = nullopt;
-        ::new(_VSTD::addressof(this->__val_)) value_type(__il, _VSTD::forward<_Args>(__args)...);
+        ::new((void*)_VSTD::addressof(this->__val_))
+            value_type(__il, _VSTD::forward<_Args>(__args)...);
         this->__engaged_ = true;
     }
 
@@ -464,12 +467,14 @@ public:
         {
             if (this->__engaged_)
             {
-                ::new(_VSTD::addressof(__opt.__val_)) value_type(_VSTD::move(this->__val_));
+                ::new((void*)_VSTD::addressof(__opt.__val_))
+                    value_type(_VSTD::move(this->__val_));
                 this->__val_.~value_type();
             }
             else
             {
-                ::new(_VSTD::addressof(this->__val_)) value_type(_VSTD::move(__opt.__val_));
+                ::new((void*)_VSTD::addressof(this->__val_))
+                    value_type(_VSTD::move(__opt.__val_));
                 __opt.__val_.~value_type();
             }
             swap(this->__engaged_, __opt.__engaged_);
@@ -901,4 +906,4 @@ _LIBCPP_END_NAMESPACE_STD
 
 #endif  // _LIBCPP_STD_VER > 11
 
-#endif  // _LIBCPP_OPTIONAL
+#endif  // _LIBCPP_EXPERIMENTAL_OPTIONAL

Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp Tue Sep  6 20:56:07 2016
@@ -19,6 +19,14 @@
 
 using std::experimental::optional;
 
+struct AllowConstAssign {
+  AllowConstAssign() = default;
+  AllowConstAssign(AllowConstAssign const&) {}
+  AllowConstAssign const& operator=(AllowConstAssign const&) const {
+      return *this;
+  }
+};
+
 struct X
 {
 };
@@ -53,6 +61,11 @@ int main()
         assert(*opt == i);
     }
     {
+        optional<const AllowConstAssign> opt;
+        const AllowConstAssign other;
+        opt = other;
+    }
+    {
         optional<std::unique_ptr<int>> opt;
         opt = std::unique_ptr<int>(new int(3));
         assert(static_cast<bool>(opt) == true);

Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp Tue Sep  6 20:56:07 2016
@@ -19,6 +19,13 @@
 
 using std::experimental::optional;
 
+struct AllowConstAssign {
+  AllowConstAssign(AllowConstAssign const&) {}
+  AllowConstAssign const& operator=(AllowConstAssign const&) const {
+      return *this;
+  }
+};
+
 struct X
 {
     static bool throw_now;
@@ -43,6 +50,11 @@ int main()
         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
     }
     {
+        optional<const AllowConstAssign> opt;
+        optional<const AllowConstAssign> opt2;
+        opt = opt2;
+    }
+    {
         optional<int> opt;
         constexpr optional<int> opt2(2);
         opt = opt2;

Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp Tue Sep  6 20:56:07 2016
@@ -81,6 +81,12 @@ int main()
         assert(*opt == 1);
     }
     {
+        optional<const int> opt(2);
+        opt.emplace(1);
+        assert(static_cast<bool>(opt) == true);
+        assert(*opt == 1);
+    }
+    {
         optional<X> opt;
         opt.emplace();
         assert(static_cast<bool>(opt) == true);

Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp Tue Sep  6 20:56:07 2016
@@ -81,6 +81,17 @@ int main()
             assert(*opt == X({1, 2}));
         }
     }
+    X::dtor_called = false;
+    {
+        X x;
+        {
+            optional<const X> opt(x);
+            assert(X::dtor_called == false);
+            opt.emplace({1, 2});
+            assert(X::dtor_called == true);
+            assert(*opt == X({1, 2}));
+        }
+    }
     {
         optional<std::vector<int>> opt;
         opt.emplace({1, 2, 3}, std::allocator<int>());

Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp Tue Sep  6 20:56:07 2016
@@ -21,6 +21,13 @@
 
 using std::experimental::optional;
 
+struct AllowConstAssign {
+  AllowConstAssign(AllowConstAssign const&) {}
+  AllowConstAssign const& operator=(AllowConstAssign const&) const {
+      return *this;
+  }
+};
+
 struct X
 {
     static bool throw_now;
@@ -77,6 +84,11 @@ int main()
         assert(*opt == *opt2);
     }
     {
+        optional<const AllowConstAssign> opt;
+        optional<const AllowConstAssign> opt2;
+        opt = std::move(opt2);
+    }
+    {
         static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
         optional<X> opt;
         optional<X> opt2(X{});

Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp Tue Sep  6 20:56:07 2016
@@ -88,6 +88,11 @@ int main()
         test(rhs);
     }
     {
+        typedef const int T;
+        optional<T> rhs(3);
+        test(rhs);
+    }
+    {
         typedef X T;
         optional<T> rhs;
         test(rhs);
@@ -97,6 +102,11 @@ int main()
         optional<T> rhs(X(3));
         test(rhs);
     }
+    {
+        typedef const X T;
+        optional<T> rhs(X(3));
+        test(rhs);
+    }
     {
         typedef Y T;
         optional<T> rhs;

Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp Tue Sep  6 20:56:07 2016
@@ -74,6 +74,17 @@ public:
     friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
 };
 
+
+class ConstMovable
+{
+    int i_;
+public:
+    ConstMovable(int i) : i_(i) {}
+    ConstMovable(const ConstMovable&& x) : i_(x.i_) {}
+    ~ConstMovable() {i_ = 0;}
+    friend bool operator==(const ConstMovable& x, const ConstMovable& y) {return x.i_ == y.i_;}
+};
+
 int main()
 {
     {
@@ -87,6 +98,11 @@ int main()
         test(rhs);
     }
     {
+        typedef const int T;
+        optional<T> rhs(3);
+        test(rhs);
+    }
+    {
         typedef X T;
         optional<T> rhs;
         test(rhs);
@@ -97,6 +113,11 @@ int main()
         test(rhs);
     }
     {
+        typedef const ConstMovable T;
+        optional<T> rhs(ConstMovable(3));
+        test(rhs);
+    }
+    {
         typedef Y T;
         optional<T> rhs;
         test(rhs);

Modified: libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp?rev=280775&r1=280774&r2=280775&view=diff
==============================================================================
--- libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp (original)
+++ libcxx/trunk/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp Tue Sep  6 20:56:07 2016
@@ -62,6 +62,10 @@ public:
     friend void swap(Z& x, Z& y) {throw 6;}
 };
 
+struct ConstSwappable {
+};
+void swap(ConstSwappable const&, ConstSwappable const&) {}
+
 int main()
 {
     {
@@ -113,6 +117,11 @@ int main()
         assert(*opt2 == 1);
     }
     {
+        optional<const ConstSwappable> opt;
+        optional<const ConstSwappable> opt2;
+        opt.swap(opt2);
+    }
+    {
         optional<X> opt1;
         optional<X> opt2;
         static_assert(noexcept(opt1.swap(opt2)) == true, "");




More information about the cfe-commits mailing list