130862412SMarshall Clow //===----------------------------------------------------------------------===//
230862412SMarshall Clow //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630862412SMarshall Clow //
730862412SMarshall Clow //===----------------------------------------------------------------------===//
830862412SMarshall Clow 
954644993SChristopher Di Bella // REQUIRES: c++17
1030862412SMarshall Clow // <optional>
1130862412SMarshall Clow 
1230862412SMarshall Clow // constexpr optional(const optional<T>&& rhs);
1307161d6dSMarshall Clow //  C++17 said:
1430862412SMarshall Clow //   If is_trivially_move_constructible_v<T> is true,
1530862412SMarshall Clow //    this constructor shall be a constexpr constructor.
1607161d6dSMarshall Clow //
1707161d6dSMarshall Clow //  P0602 changed this to:
1807161d6dSMarshall Clow //     If is_trivially_move_constructible_v<T> is true, this constructor is trivial.
1907161d6dSMarshall Clow //
2007161d6dSMarshall Clow //  which means that it can't be constexpr if T is not trivially move-constructible,
2107161d6dSMarshall Clow //    because you have to do a placement new to get the value into place.
2207161d6dSMarshall Clow //    Except in the case where it is moving from an empty optional - that could be
2307161d6dSMarshall Clow //    made to be constexpr (and libstdc++ does so).
2430862412SMarshall Clow 
2530862412SMarshall Clow #include <optional>
2630862412SMarshall Clow #include <type_traits>
2730862412SMarshall Clow #include <cassert>
2830862412SMarshall Clow 
2930862412SMarshall Clow #include "test_macros.h"
3030862412SMarshall Clow 
3130862412SMarshall Clow struct S {
SS3230862412SMarshall Clow     constexpr S()   : v_(0) {}
SS3330862412SMarshall Clow     S(int v)        : v_(v) {}
SS3430862412SMarshall Clow     constexpr S(const S  &rhs) : v_(rhs.v_) {} // not trivially moveable
SS3507161d6dSMarshall Clow     constexpr S(      S &&rhs) : v_(rhs.v_) {} // not trivially moveable
3630862412SMarshall Clow     int v_;
3730862412SMarshall Clow     };
3830862412SMarshall Clow 
3930862412SMarshall Clow 
test()4007161d6dSMarshall Clow constexpr bool test() // expected-error {{constexpr function never produces a constant expression}}
4107161d6dSMarshall Clow {
4207161d6dSMarshall Clow     std::optional<S> o1{3};
4307161d6dSMarshall Clow     std::optional<S> o2 = std::move(o1);
4407161d6dSMarshall Clow     return o2.has_value();  // return -something-
4507161d6dSMarshall Clow }
4607161d6dSMarshall Clow 
4707161d6dSMarshall Clow 
main(int,char **)482df59c50SJF Bastien int main(int, char**)
4930862412SMarshall Clow {
5030862412SMarshall Clow     static_assert (!std::is_trivially_move_constructible_v<S>, "" );
51*76476efdSMuhammad Usman Shahid     static_assert (test(), "");  // expected-error-re {{{{(static_assert|static assertion)}} expression is not an integral constant expression}}
522df59c50SJF Bastien     return 0;
5330862412SMarshall Clow }
54