Nikolas Klauser 34d4f0c136
[libc++][NFC] Use llvm.org/PR to link to bug reports (#156288)
We've built up quite a few links directly to github within the code
base. We should instead use `llvm.org/PR<issue-number>` to link to bugs,
since that is resilient to the bug tracker changing in the future. This
is especially relevant for tests linking to bugs, since they will
probably be there for decades to come. A nice side effect is that these
links are significantly shorter than the GH links, making them much less
of an eyesore.

This patch also replaces a few links that linked to the old bugzilla
instance on llvm.org.
2025-09-04 09:20:02 +02:00

171 lines
6.1 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: c++03, c++11, c++14
// <numeric>
// template<class _M, class _N>
// constexpr common_type_t<_M,_N> lcm(_M __m, _N __n)
#include <numeric>
#include <cassert>
#include <climits>
#include <cstdint>
#include <limits>
#include <type_traits>
#include "test_macros.h"
constexpr struct {
int x;
int y;
int expect;
} Cases[] = {
{0, 0, 0},
{1, 0, 0},
{0, 1, 0},
{1, 1, 1},
{2, 3, 6},
{2, 4, 4},
{3, 17, 51},
{36, 18, 36}
};
template <typename Input1, typename Input2, typename Output>
constexpr bool test0(int in1, int in2, int out)
{
auto value1 = static_cast<Input1>(in1);
auto value2 = static_cast<Input2>(in2);
static_assert(std::is_same_v<Output, decltype(std::lcm(value1, value2))>, "");
static_assert(std::is_same_v<Output, decltype(std::lcm(value2, value1))>, "");
assert(static_cast<Output>(out) == std::lcm(value1, value2));
return true;
}
template <typename Input1, typename Input2 = Input1>
constexpr bool do_test(int = 0)
{
using S1 = std::make_signed_t<Input1>;
using S2 = std::make_signed_t<Input2>;
using U1 = std::make_unsigned_t<Input1>;
using U2 = std::make_unsigned_t<Input2>;
bool accumulate = true;
for (auto TC : Cases) {
{ // Test with two signed types
using Output = std::common_type_t<S1, S2>;
accumulate &= test0<S1, S2, Output>(TC.x, TC.y, TC.expect);
accumulate &= test0<S1, S2, Output>(-TC.x, TC.y, TC.expect);
accumulate &= test0<S1, S2, Output>(TC.x, -TC.y, TC.expect);
accumulate &= test0<S1, S2, Output>(-TC.x, -TC.y, TC.expect);
accumulate &= test0<S2, S1, Output>(TC.x, TC.y, TC.expect);
accumulate &= test0<S2, S1, Output>(-TC.x, TC.y, TC.expect);
accumulate &= test0<S2, S1, Output>(TC.x, -TC.y, TC.expect);
accumulate &= test0<S2, S1, Output>(-TC.x, -TC.y, TC.expect);
}
{ // test with two unsigned types
using Output = std::common_type_t<U1, U2>;
accumulate &= test0<U1, U2, Output>(TC.x, TC.y, TC.expect);
accumulate &= test0<U2, U1, Output>(TC.x, TC.y, TC.expect);
}
{ // Test with mixed signs
using Output = std::common_type_t<S1, U2>;
accumulate &= test0<S1, U2, Output>(TC.x, TC.y, TC.expect);
accumulate &= test0<U2, S1, Output>(TC.x, TC.y, TC.expect);
accumulate &= test0<S1, U2, Output>(-TC.x, TC.y, TC.expect);
accumulate &= test0<U2, S1, Output>(TC.x, -TC.y, TC.expect);
}
{ // Test with mixed signs
using Output = std::common_type_t<S2, U1>;
accumulate &= test0<S2, U1, Output>(TC.x, TC.y, TC.expect);
accumulate &= test0<U1, S2, Output>(TC.x, TC.y, TC.expect);
accumulate &= test0<S2, U1, Output>(-TC.x, TC.y, TC.expect);
accumulate &= test0<U1, S2, Output>(TC.x, -TC.y, TC.expect);
}
}
return accumulate;
}
template <class T>
constexpr bool test_limits() {
assert(std::lcm(std::numeric_limits<T>::max() - 1, std::numeric_limits<T>::max() - 1) == std::numeric_limits<T>::max() - 1);
assert(std::lcm(std::numeric_limits<T>::max(), std::numeric_limits<T>::max()) == std::numeric_limits<T>::max());
return true;
}
int main(int argc, char**)
{
int non_cce = argc; // a value that can't possibly be constexpr
static_assert(do_test<signed char>(), "");
static_assert(do_test<short>(), "");
static_assert(do_test<int>(), "");
static_assert(do_test<long>(), "");
static_assert(do_test<long long>(), "");
assert(do_test<signed char>(non_cce));
assert(do_test<short>(non_cce));
assert(do_test<int>(non_cce));
assert(do_test<long>(non_cce));
assert(do_test<long long>(non_cce));
static_assert(do_test<std::int8_t>(), "");
static_assert(do_test<std::int16_t>(), "");
static_assert(do_test<std::int32_t>(), "");
static_assert(do_test<std::int64_t>(), "");
assert(do_test<std::int8_t>(non_cce));
assert(do_test<std::int16_t>(non_cce));
assert(do_test<std::int32_t>(non_cce));
assert(do_test<std::int64_t>(non_cce));
static_assert(do_test<signed char, int>(), "");
static_assert(do_test<int, signed char>(), "");
static_assert(do_test<short, int>(), "");
static_assert(do_test<int, short>(), "");
static_assert(do_test<int, long>(), "");
static_assert(do_test<long, int>(), "");
static_assert(do_test<int, long long>(), "");
static_assert(do_test<long long, int>(), "");
assert((do_test<signed char, int>(non_cce)));
assert((do_test<int, signed char>(non_cce)));
assert((do_test<short, int>(non_cce)));
assert((do_test<int, short>(non_cce)));
assert((do_test<int, long>(non_cce)));
assert((do_test<long, int>(non_cce)));
assert((do_test<int, long long>(non_cce)));
assert((do_test<long long, int>(non_cce)));
// LWG#2837
{
auto res1 = std::lcm(static_cast<std::int64_t>(1234), INT32_MIN);
TEST_IGNORE_NODISCARD std::lcm(INT_MIN, 2UL); // this used to trigger UBSAN
static_assert(std::is_same_v<decltype(res1), std::int64_t>, "");
assert(res1 == 1324997410816LL);
}
// https://llvm.org/PR96196
{
assert(test_limits<unsigned int>());
assert(test_limits<std::uint32_t>());
assert(test_limits<std::uint64_t>());
assert(test_limits<int>());
assert(test_limits<std::int32_t>());
assert(test_limits<std::int64_t>());
static_assert(test_limits<unsigned int>(), "");
static_assert(test_limits<std::uint32_t>(), "");
static_assert(test_limits<std::uint64_t>(), "");
static_assert(test_limits<int>(), "");
static_assert(test_limits<std::int32_t>(), "");
static_assert(test_limits<std::int64_t>(), "");
}
return 0;
}