143e42141SMarek Kurdej //===----------------------------------------------------------------------===//
243e42141SMarek Kurdej //
343e42141SMarek Kurdej // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
443e42141SMarek Kurdej // See https://llvm.org/LICENSE.txt for license information.
543e42141SMarek Kurdej // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
643e42141SMarek Kurdej //
743e42141SMarek Kurdej //===----------------------------------------------------------------------===//
843e42141SMarek Kurdej
98508b1c1SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
1043e42141SMarek Kurdej
1143e42141SMarek Kurdej // [utility.underlying], to_underlying
1243e42141SMarek Kurdej // template <class T>
13*71400505SMark de Wever // constexpr underlying_type_t<T> to_underlying( T value ) noexcept; // C++23
1443e42141SMarek Kurdej
1543e42141SMarek Kurdej #include <utility>
1643e42141SMarek Kurdej #include <cassert>
1769d5a666SChristopher Di Bella #include <cstdint>
1843e42141SMarek Kurdej #include <limits>
1943e42141SMarek Kurdej
2043e42141SMarek Kurdej #include "test_macros.h"
2143e42141SMarek Kurdej
2243e42141SMarek Kurdej enum class e_default { a = 0, b = 1, c = 2 };
2343e42141SMarek Kurdej enum class e_ushort : unsigned short { d = 10, e = 25, f = 50 };
2443e42141SMarek Kurdej enum class e_longlong : long long {
2543e42141SMarek Kurdej low = std::numeric_limits<long long>::min(),
2643e42141SMarek Kurdej high = std::numeric_limits<long long>::max()
2743e42141SMarek Kurdej };
2843e42141SMarek Kurdej enum e_non_class { enum_a = 10, enum_b = 11, enum_c = 12 };
2943e42141SMarek Kurdej enum e_int : int {
3043e42141SMarek Kurdej enum_min = std::numeric_limits<int>::min(),
3143e42141SMarek Kurdej enum_max = std::numeric_limits<int>::max()
3243e42141SMarek Kurdej };
3343e42141SMarek Kurdej enum class e_bool : std::uint8_t { f = 0, t = 1 };
3443e42141SMarek Kurdej
3543e42141SMarek Kurdej struct WithBitfieldEnums {
3643e42141SMarek Kurdej e_default e1 : 3;
3743e42141SMarek Kurdej e_ushort e2 : 6;
3843e42141SMarek Kurdej e_bool e3 : 1;
3943e42141SMarek Kurdej };
4043e42141SMarek Kurdej
test()4143e42141SMarek Kurdej constexpr bool test() {
4243e42141SMarek Kurdej ASSERT_NOEXCEPT(std::to_underlying(e_default::a));
4343e42141SMarek Kurdej ASSERT_SAME_TYPE(int, decltype(std::to_underlying(e_default::a)));
4443e42141SMarek Kurdej ASSERT_SAME_TYPE(unsigned short, decltype(std::to_underlying(e_ushort::d)));
4543e42141SMarek Kurdej ASSERT_SAME_TYPE(long long, decltype(std::to_underlying(e_longlong::low)));
4643e42141SMarek Kurdej ASSERT_SAME_TYPE(int, decltype(std::to_underlying(enum_min)));
4743e42141SMarek Kurdej ASSERT_SAME_TYPE(int, decltype(std::to_underlying(enum_max)));
4843e42141SMarek Kurdej
4943e42141SMarek Kurdej assert(0 == std::to_underlying(e_default::a));
5043e42141SMarek Kurdej assert(1 == std::to_underlying(e_default::b));
5143e42141SMarek Kurdej assert(2 == std::to_underlying(e_default::c));
5243e42141SMarek Kurdej
5343e42141SMarek Kurdej assert(10 == std::to_underlying(e_ushort::d));
5443e42141SMarek Kurdej assert(25 == std::to_underlying(e_ushort::e));
5543e42141SMarek Kurdej assert(50 == std::to_underlying(e_ushort::f));
5643e42141SMarek Kurdej
5743e42141SMarek Kurdej // Check no truncating.
5843e42141SMarek Kurdej assert(std::numeric_limits<long long>::min() ==
5943e42141SMarek Kurdej std::to_underlying(e_longlong::low));
6043e42141SMarek Kurdej assert(std::numeric_limits<long long>::max() ==
6143e42141SMarek Kurdej std::to_underlying(e_longlong::high));
6243e42141SMarek Kurdej
6343e42141SMarek Kurdej assert(10 == std::to_underlying(enum_a));
6443e42141SMarek Kurdej assert(11 == std::to_underlying(enum_b));
6543e42141SMarek Kurdej assert(12 == std::to_underlying(enum_c));
6643e42141SMarek Kurdej assert(std::numeric_limits<int>::min() == std::to_underlying(enum_min));
6743e42141SMarek Kurdej assert(std::numeric_limits<int>::max() == std::to_underlying(enum_max));
6843e42141SMarek Kurdej
6943e42141SMarek Kurdej WithBitfieldEnums bf;
7043e42141SMarek Kurdej bf.e1 = static_cast<e_default>(3);
7143e42141SMarek Kurdej bf.e2 = e_ushort::e;
7243e42141SMarek Kurdej bf.e3 = e_bool::t;
7343e42141SMarek Kurdej assert(3 == std::to_underlying(bf.e1));
7443e42141SMarek Kurdej assert(25 == std::to_underlying(bf.e2));
7543e42141SMarek Kurdej assert(1 == std::to_underlying(bf.e3));
7643e42141SMarek Kurdej
7743e42141SMarek Kurdej return true;
7843e42141SMarek Kurdej }
7943e42141SMarek Kurdej
main(int,char **)8043e42141SMarek Kurdej int main(int, char**) {
8143e42141SMarek Kurdej test();
8243e42141SMarek Kurdej static_assert(test());
8343e42141SMarek Kurdej
8443e42141SMarek Kurdej return 0;
8543e42141SMarek Kurdej }
86