87 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 11// constexpr bool has_value() const noexcept;12 13#include <cassert>14#include <concepts>15#include <expected>16#include <optional>17#include <type_traits>18#include <utility>19 20#include "test_macros.h"21#include "../../types.h"22 23// Test noexcept24template <class T>25concept HasValueNoexcept =26 requires(T t) {27 { t.has_value() } noexcept;28 };29 30struct Foo {};31static_assert(!HasValueNoexcept<Foo>);32 33static_assert(HasValueNoexcept<std::expected<int, int>>);34static_assert(HasValueNoexcept<const std::expected<int, int>>);35 36constexpr bool test() {37 // has_value38 {39 const std::expected<int, int> e(5);40 assert(e.has_value());41 }42 43 // !has_value44 {45 const std::expected<int, int> e(std::unexpect, 5);46 assert(!e.has_value());47 }48 49 // The following tests check that the "has_value" flag is not overwritten50 // by the constructor of the value. This could happen because the flag is51 // stored in the tail padding of the value.52 //53 // The first test is a simplified version of the real code where this was54 // first observed.55 //56 // The other tests use a synthetic struct that clobbers its tail padding57 // on construction, making the issue easier to reproduce.58 //59 // See https://llvm.org/PR68552 and the linked PR.60 {61 auto f1 = []() -> std::expected<std::optional<int>, long> { return 0; };62 63 auto f2 = [&f1]() -> std::expected<std::optional<int>, int> {64 return f1().transform_error([](auto) { return 0; });65 };66 67 auto e = f2();68 assert(e.has_value());69 }70 {71 const std::expected<TailClobberer<0>, bool> e = {};72 // clang-cl does not support [[no_unique_address]] yet.73#if !(defined(TEST_COMPILER_CLANG) && defined(_MSC_VER))74 LIBCPP_STATIC_ASSERT(sizeof(TailClobberer<0>) == sizeof(e));75#endif76 assert(e.has_value());77 }78 79 return true;80}81 82int main(int, char**) {83 test();84 static_assert(test());85 return 0;86}87