1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14
12 // template<class _M, class _N>
13 // constexpr common_type_t<_M,_N> lcm(_M __m, _N __n)
19 #include <type_traits>
20 #include "test_macros.h"
37 template <typename Input1
, typename Input2
, typename Output
>
38 constexpr bool test0(int in1
, int in2
, int out
)
40 auto value1
= static_cast<Input1
>(in1
);
41 auto value2
= static_cast<Input2
>(in2
);
42 static_assert(std::is_same_v
<Output
, decltype(std::lcm(value1
, value2
))>, "");
43 static_assert(std::is_same_v
<Output
, decltype(std::lcm(value2
, value1
))>, "");
44 assert(static_cast<Output
>(out
) == std::lcm(value1
, value2
));
49 template <typename Input1
, typename Input2
= Input1
>
50 constexpr bool do_test(int = 0)
52 using S1
= std::make_signed_t
<Input1
>;
53 using S2
= std::make_signed_t
<Input2
>;
54 using U1
= std::make_unsigned_t
<Input1
>;
55 using U2
= std::make_unsigned_t
<Input2
>;
56 bool accumulate
= true;
57 for (auto TC
: Cases
) {
58 { // Test with two signed types
59 using Output
= std::common_type_t
<S1
, S2
>;
60 accumulate
&= test0
<S1
, S2
, Output
>(TC
.x
, TC
.y
, TC
.expect
);
61 accumulate
&= test0
<S1
, S2
, Output
>(-TC
.x
, TC
.y
, TC
.expect
);
62 accumulate
&= test0
<S1
, S2
, Output
>(TC
.x
, -TC
.y
, TC
.expect
);
63 accumulate
&= test0
<S1
, S2
, Output
>(-TC
.x
, -TC
.y
, TC
.expect
);
64 accumulate
&= test0
<S2
, S1
, Output
>(TC
.x
, TC
.y
, TC
.expect
);
65 accumulate
&= test0
<S2
, S1
, Output
>(-TC
.x
, TC
.y
, TC
.expect
);
66 accumulate
&= test0
<S2
, S1
, Output
>(TC
.x
, -TC
.y
, TC
.expect
);
67 accumulate
&= test0
<S2
, S1
, Output
>(-TC
.x
, -TC
.y
, TC
.expect
);
69 { // test with two unsigned types
70 using Output
= std::common_type_t
<U1
, U2
>;
71 accumulate
&= test0
<U1
, U2
, Output
>(TC
.x
, TC
.y
, TC
.expect
);
72 accumulate
&= test0
<U2
, U1
, Output
>(TC
.x
, TC
.y
, TC
.expect
);
74 { // Test with mixed signs
75 using Output
= std::common_type_t
<S1
, U2
>;
76 accumulate
&= test0
<S1
, U2
, Output
>(TC
.x
, TC
.y
, TC
.expect
);
77 accumulate
&= test0
<U2
, S1
, Output
>(TC
.x
, TC
.y
, TC
.expect
);
78 accumulate
&= test0
<S1
, U2
, Output
>(-TC
.x
, TC
.y
, TC
.expect
);
79 accumulate
&= test0
<U2
, S1
, Output
>(TC
.x
, -TC
.y
, TC
.expect
);
81 { // Test with mixed signs
82 using Output
= std::common_type_t
<S2
, U1
>;
83 accumulate
&= test0
<S2
, U1
, Output
>(TC
.x
, TC
.y
, TC
.expect
);
84 accumulate
&= test0
<U1
, S2
, Output
>(TC
.x
, TC
.y
, TC
.expect
);
85 accumulate
&= test0
<S2
, U1
, Output
>(-TC
.x
, TC
.y
, TC
.expect
);
86 accumulate
&= test0
<U1
, S2
, Output
>(TC
.x
, -TC
.y
, TC
.expect
);
92 int main(int argc
, char**)
94 int non_cce
= argc
; // a value that can't possibly be constexpr
96 static_assert(do_test
<signed char>(), "");
97 static_assert(do_test
<short>(), "");
98 static_assert(do_test
<int>(), "");
99 static_assert(do_test
<long>(), "");
100 static_assert(do_test
<long long>(), "");
102 assert(do_test
<signed char>(non_cce
));
103 assert(do_test
<short>(non_cce
));
104 assert(do_test
<int>(non_cce
));
105 assert(do_test
<long>(non_cce
));
106 assert(do_test
<long long>(non_cce
));
108 static_assert(do_test
<std::int8_t>(), "");
109 static_assert(do_test
<std::int16_t>(), "");
110 static_assert(do_test
<std::int32_t>(), "");
111 static_assert(do_test
<std::int64_t>(), "");
113 assert(do_test
<std::int8_t>(non_cce
));
114 assert(do_test
<std::int16_t>(non_cce
));
115 assert(do_test
<std::int32_t>(non_cce
));
116 assert(do_test
<std::int64_t>(non_cce
));
118 static_assert(do_test
<signed char, int>(), "");
119 static_assert(do_test
<int, signed char>(), "");
120 static_assert(do_test
<short, int>(), "");
121 static_assert(do_test
<int, short>(), "");
122 static_assert(do_test
<int, long>(), "");
123 static_assert(do_test
<long, int>(), "");
124 static_assert(do_test
<int, long long>(), "");
125 static_assert(do_test
<long long, int>(), "");
127 assert((do_test
<signed char, int>(non_cce
)));
128 assert((do_test
<int, signed char>(non_cce
)));
129 assert((do_test
<short, int>(non_cce
)));
130 assert((do_test
<int, short>(non_cce
)));
131 assert((do_test
<int, long>(non_cce
)));
132 assert((do_test
<long, int>(non_cce
)));
133 assert((do_test
<int, long long>(non_cce
)));
134 assert((do_test
<long long, int>(non_cce
)));
138 auto res1
= std::lcm(static_cast<std::int64_t>(1234), INT32_MIN
);
139 TEST_IGNORE_NODISCARD
std::lcm(INT_MIN
, 2UL); // this used to trigger UBSAN
140 static_assert(std::is_same_v
<decltype(res1
), std::int64_t>, "");
141 assert(res1
== 1324997410816LL);