1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // REQUIRES: c++17
10 // <optional>
11 
12 // constexpr optional(const optional<T>&& rhs);
13 //  C++17 said:
14 //   If is_trivially_move_constructible_v<T> is true,
15 //    this constructor shall be a constexpr constructor.
16 //
17 //  P0602 changed this to:
18 //     If is_trivially_move_constructible_v<T> is true, this constructor is trivial.
19 //
20 //  which means that it can't be constexpr if T is not trivially move-constructible,
21 //    because you have to do a placement new to get the value into place.
22 //    Except in the case where it is moving from an empty optional - that could be
23 //    made to be constexpr (and libstdc++ does so).
24 
25 #include <optional>
26 #include <type_traits>
27 #include <cassert>
28 
29 #include "test_macros.h"
30 
31 struct S {
SS32     constexpr S()   : v_(0) {}
SS33     S(int v)        : v_(v) {}
SS34     constexpr S(const S  &rhs) : v_(rhs.v_) {} // not trivially moveable
SS35     constexpr S(      S &&rhs) : v_(rhs.v_) {} // not trivially moveable
36     int v_;
37     };
38 
39 
test()40 constexpr bool test() // expected-error {{constexpr function never produces a constant expression}}
41 {
42     std::optional<S> o1{3};
43     std::optional<S> o2 = std::move(o1);
44     return o2.has_value();  // return -something-
45 }
46 
47 
main(int,char **)48 int main(int, char**)
49 {
50     static_assert (!std::is_trivially_move_constructible_v<S>, "" );
51     static_assert (test(), "");  // expected-error-re {{{{(static_assert|static assertion)}} expression is not an integral constant expression}}
52     return 0;
53 }
54