summaryrefslogtreecommitdiff
path: root/libcxx
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2016-09-07 01:56:07 +0000
committerEric Fiselier <eric@efcs.ca>2016-09-07 01:56:07 +0000
commitef853e978058cc57d2b5f0bcf0ee0e3a34528655 (patch)
tree909b312817f1a5263ad427ff44253129d75c8223 /libcxx
parent23e51e4905aa0da19174a9973a95adce6809a7c6 (diff)
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.
Diffstat (limited to 'libcxx')
-rw-r--r--libcxx/include/experimental/optional33
-rw-r--r--libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp13
-rw-r--r--libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp12
-rw-r--r--libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp6
-rw-r--r--libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp11
-rw-r--r--libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp12
-rw-r--r--libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp10
-rw-r--r--libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp21
-rw-r--r--libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp9
9 files changed, 113 insertions, 14 deletions
diff --git a/libcxx/include/experimental/optional b/libcxx/include/experimental/optional
index 11bf8678da0..966c889e99d 100644
--- a/libcxx/include/experimental/optional
+++ b/libcxx/include/experimental/optional
@@ -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
diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp
index 3d0d2e03158..27aafe0df6b 100644
--- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp
+++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/assign_value.pass.cpp
@@ -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);
diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp
index 89ea345029c..ff37b22c7d2 100644
--- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp
+++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/copy.pass.cpp
@@ -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;
diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp
index 94f2bb21a47..6a7b56e588d 100644
--- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp
+++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace.pass.cpp
@@ -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);
diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
index fec37408e43..b02616ef995 100644
--- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
+++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
@@ -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>());
diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp
index fa00f5602c7..1c3b780677e 100644
--- a/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp
+++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.assign/move.pass.cpp
@@ -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{});
diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp
index 144af2e3a7d..c7c687caf53 100644
--- a/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp
+++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/copy.pass.cpp
@@ -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);
@@ -98,6 +103,11 @@ int main()
test(rhs);
}
{
+ typedef const X T;
+ optional<T> rhs(X(3));
+ test(rhs);
+ }
+ {
typedef Y T;
optional<T> rhs;
test(rhs);
diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp
index 851157f960f..4ed0c92e026 100644
--- a/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp
+++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.ctor/move.pass.cpp
@@ -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);
diff --git a/libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp b/libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp
index 620dda19e3f..be0d1efb60d 100644
--- a/libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp
+++ b/libcxx/test/std/experimental/optional/optional.object/optional.object.swap/swap.pass.cpp
@@ -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, "");