brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.2 KiB · 43ca96e Raw
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