[libcxx-commits] [libcxx] [libc++][ratio] Avoids accepting unrelated types. (PR #80491)

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sat Feb 10 05:42:55 PST 2024


https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/80491

>From e982e810b0dc05fe936c459f93a0cbeda1f8f7fe Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Fri, 2 Feb 2024 21:43:30 +0100
Subject: [PATCH 1/2] [libc++][ratio] Avoids accepting unrelated types.

The arithemtic and comparison operations are ill-formed when R1 or R2 is
not a std::ratio.

Fixes: https://github.com/llvm/llvm-project/issues/63753
---
 libcxx/include/ratio                          | 42 ++++++++--
 .../R1_R2_requirement.verify.cpp              | 50 ++++++++++++
 .../R1_R2_requirement.verify.cpp              | 65 ++++++++++++++++
 .../R1_R2_requirement_v.verify.cpp            | 77 +++++++++++++++++++
 4 files changed, 228 insertions(+), 6 deletions(-)
 create mode 100644 libcxx/test/std/utilities/ratio/ratio.arithmetic/R1_R2_requirement.verify.cpp
 create mode 100644 libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement.verify.cpp
 create mode 100644 libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement_v.verify.cpp

diff --git a/libcxx/include/ratio b/libcxx/include/ratio
index 3b11a2aa5bf6e7..de656f38e01de6 100644
--- a/libcxx/include/ratio
+++ b/libcxx/include/ratio
@@ -289,6 +289,9 @@ private:
   static const intmax_t __gcd_n1_d2 = __static_gcd<_R1::num, _R2::den>::value;
   static const intmax_t __gcd_d1_n2 = __static_gcd<_R1::den, _R2::num>::value;
 
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+
 public:
   typedef typename ratio< __ll_mul<_R1::num / __gcd_n1_d2, _R2::num / __gcd_d1_n2>::value,
                           __ll_mul<_R2::den / __gcd_n1_d2, _R1::den / __gcd_d1_n2>::value >::type type;
@@ -312,6 +315,9 @@ private:
   static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value;
   static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value;
 
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+
 public:
   typedef typename ratio< __ll_mul<_R1::num / __gcd_n1_n2, _R2::den / __gcd_d1_d2>::value,
                           __ll_mul<_R2::num / __gcd_n1_n2, _R1::den / __gcd_d1_d2>::value >::type type;
@@ -335,6 +341,9 @@ private:
   static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value;
   static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value;
 
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+
 public:
   typedef typename ratio_multiply<
       ratio<__gcd_n1_n2, _R1::den / __gcd_d1_d2>,
@@ -361,6 +370,9 @@ private:
   static const intmax_t __gcd_n1_n2 = __static_gcd<_R1::num, _R2::num>::value;
   static const intmax_t __gcd_d1_d2 = __static_gcd<_R1::den, _R2::den>::value;
 
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+
 public:
   typedef typename ratio_multiply<
       ratio<__gcd_n1_n2, _R1::den / __gcd_d1_d2>,
@@ -384,10 +396,16 @@ struct _LIBCPP_TEMPLATE_VIS ratio_subtract : public __ratio_subtract<_R1, _R2>::
 // ratio_equal
 
 template <class _R1, class _R2>
-struct _LIBCPP_TEMPLATE_VIS ratio_equal : _BoolConstant<(_R1::num == _R2::num && _R1::den == _R2::den)> {};
+struct _LIBCPP_TEMPLATE_VIS ratio_equal : _BoolConstant<(_R1::num == _R2::num && _R1::den == _R2::den)> {
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+};
 
 template <class _R1, class _R2>
-struct _LIBCPP_TEMPLATE_VIS ratio_not_equal : _BoolConstant<!ratio_equal<_R1, _R2>::value> {};
+struct _LIBCPP_TEMPLATE_VIS ratio_not_equal : _BoolConstant<!ratio_equal<_R1, _R2>::value> {
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+};
 
 // ratio_less
 
@@ -441,16 +459,28 @@ struct __ratio_less<_R1, _R2, -1LL, -1LL> {
 };
 
 template <class _R1, class _R2>
-struct _LIBCPP_TEMPLATE_VIS ratio_less : _BoolConstant<__ratio_less<_R1, _R2>::value> {};
+struct _LIBCPP_TEMPLATE_VIS ratio_less : _BoolConstant<__ratio_less<_R1, _R2>::value> {
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+};
 
 template <class _R1, class _R2>
-struct _LIBCPP_TEMPLATE_VIS ratio_less_equal : _BoolConstant<!ratio_less<_R2, _R1>::value> {};
+struct _LIBCPP_TEMPLATE_VIS ratio_less_equal : _BoolConstant<!ratio_less<_R2, _R1>::value> {
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+};
 
 template <class _R1, class _R2>
-struct _LIBCPP_TEMPLATE_VIS ratio_greater : _BoolConstant<ratio_less<_R2, _R1>::value> {};
+struct _LIBCPP_TEMPLATE_VIS ratio_greater : _BoolConstant<ratio_less<_R2, _R1>::value> {
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+};
 
 template <class _R1, class _R2>
-struct _LIBCPP_TEMPLATE_VIS ratio_greater_equal : _BoolConstant<!ratio_less<_R1, _R2>::value> {};
+struct _LIBCPP_TEMPLATE_VIS ratio_greater_equal : _BoolConstant<!ratio_less<_R1, _R2>::value> {
+  static_assert(__is_ratio<_R1>::value, "[ratio.general]/2 requires R1 to be a specialisation of the ratio template");
+  static_assert(__is_ratio<_R2>::value, "[ratio.general]/2 requires R2 to be a specialisation of the ratio template");
+};
 
 template <class _R1, class _R2>
 struct __ratio_gcd {
diff --git a/libcxx/test/std/utilities/ratio/ratio.arithmetic/R1_R2_requirement.verify.cpp b/libcxx/test/std/utilities/ratio/ratio.arithmetic/R1_R2_requirement.verify.cpp
new file mode 100644
index 00000000000000..93e9b1903d9407
--- /dev/null
+++ b/libcxx/test/std/utilities/ratio/ratio.arithmetic/R1_R2_requirement.verify.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <ratio>
+//
+// [ratio.general]/2
+//   Throughout subclause [ratio], the names of template parameters are
+//   used to express type requirements. If a template parameter is named
+//   R1 or R2, and the template argument is not a specialization of the
+//   ratio template, the program is ill-formed.
+//
+// test ratio_multiply
+
+#include <ratio>
+
+struct R {
+  static const int num = 1;
+  static const int den = 1;
+};
+
+using r = std::ratio<1, 1>;
+
+namespace add {
+using r_r = std::ratio_add<r, r>::type;
+using R_r = std::ratio_add<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_add<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace add
+
+namespace subtract {
+using r_r = std::ratio_subtract<r, r>::type;
+using R_r = std::ratio_subtract<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_subtract<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace subtract
+
+namespace multiply {
+using r_r = std::ratio_multiply<r, r>::type;
+using R_r = std::ratio_multiply<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_multiply<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace multiply
+
+namespace divide {
+using r_r = std::ratio_divide<r, r>::type;
+using R_r = std::ratio_divide<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_divide<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace divide
diff --git a/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement.verify.cpp b/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement.verify.cpp
new file mode 100644
index 00000000000000..4371dd99c09fab
--- /dev/null
+++ b/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement.verify.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <ratio>
+//
+// [ratio.general]/2
+//   Throughout subclause [ratio], the names of template parameters are
+//   used to express type requirements. If a template parameter is named
+//   R1 or R2, and the template argument is not a specialization of the
+//   ratio template, the program is ill-formed.
+//
+// Since std::ratio_xxx_v uses the same instantiations only one error
+// will be generated. These values are tested in a separate test.
+
+#include <ratio>
+
+struct R {
+  static const int num = 1;
+  static const int den = 1;
+};
+
+using r = std::ratio<1, 1>;
+
+namespace equal {
+using r_r = std::ratio_equal<r, r>::type;
+using R_r = std::ratio_equal<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_equal<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace equal
+
+namespace not_equal {
+using r_r = std::ratio_not_equal<r, r>::type;
+using R_r = std::ratio_not_equal<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_not_equal<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace not_equal
+
+namespace less {
+using r_r = std::ratio_less<r, r>::type;
+using R_r = std::ratio_less<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_less<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace less
+
+namespace less_equal {
+using r_r = std::ratio_less_equal<r, r>::type;
+using R_r = std::ratio_less_equal<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_less_equal<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace less_equal
+
+namespace greater {
+using r_r = std::ratio_greater<r, r>::type;
+using R_r = std::ratio_greater<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R = std::ratio_greater<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace greater
+
+namespace greater_equal {
+using r_r = std::ratio_greater_equal<r, r>::type;
+using R_r =
+    std::ratio_greater_equal<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using r_R =
+    std::ratio_greater_equal<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace greater_equal
diff --git a/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement_v.verify.cpp b/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement_v.verify.cpp
new file mode 100644
index 00000000000000..d30318249c6614
--- /dev/null
+++ b/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement_v.verify.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// 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++17
+
+// <ratio>
+//
+// [ratio.general]/2
+//   Throughout subclause [ratio], the names of template parameters are
+//   used to express type requirements. If a template parameter is named
+//   R1 or R2, and the template argument is not a specialization of the
+//   ratio template, the program is ill-formed.
+//
+// Since std::ratio_xxx uses the same instantiations only one error
+// will be generated. These types are tested in a separate test.
+
+#include <ratio>
+
+struct R {
+  constexpr static int num = 1;
+  constexpr static int den = 1;
+};
+
+using r = std::ratio<1, 1>;
+
+namespace equal {
+constexpr bool r_r_v = std::ratio_equal_v<r, r>;
+constexpr bool R_r_v =
+    std::ratio_equal_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+constexpr bool r_R_v =
+    std::ratio_equal_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace equal
+
+namespace not_equal {
+constexpr bool r_r_v = std::ratio_not_equal_v<r, r>;
+constexpr bool R_r_v =
+    std::ratio_not_equal_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+constexpr bool r_R_v =
+    std::ratio_not_equal_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace not_equal
+
+namespace less {
+constexpr bool r_r_v = std::ratio_less_v<r, r>;
+constexpr bool R_r_v =
+    std::ratio_less_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+constexpr bool r_R_v =
+    std::ratio_less_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace less
+
+namespace less_equal {
+constexpr bool r_r_v = std::ratio_less_equal_v<r, r>;
+constexpr bool R_r_v =
+    std::ratio_less_equal_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+constexpr bool r_R_v =
+    std::ratio_less_equal_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace less_equal
+
+namespace greater {
+constexpr bool r_r_v = std::ratio_greater_v<r, r>;
+constexpr bool R_r_v =
+    std::ratio_greater_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+constexpr bool r_R_v =
+    std::ratio_greater_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace greater
+
+namespace greater_equal {
+constexpr bool r_r_v = std::ratio_greater_equal_v<r, r>;
+constexpr bool R_r_v =
+    std::ratio_greater_equal_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+constexpr bool r_R_v =
+    std::ratio_greater_equal_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+} // namespace greater_equal

>From 67401b989f79f26f61bd2e71fa2598fe6810d405 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sat, 10 Feb 2024 14:42:44 +0100
Subject: [PATCH 2/2] address review comments and adds missing test.

---
 .../ratio_multiply.verify.cpp                 | 56 +++++++++++++
 .../R1_R2_requirement.verify.cpp              | 63 ++++++++------
 .../R1_R2_requirement_v.verify.cpp            | 84 +++++++++----------
 3 files changed, 133 insertions(+), 70 deletions(-)
 create mode 100644 libcxx/test/std/utilities/ratio/ratio.arithmetic/ratio_multiply.verify.cpp

diff --git a/libcxx/test/std/utilities/ratio/ratio.arithmetic/ratio_multiply.verify.cpp b/libcxx/test/std/utilities/ratio/ratio.arithmetic/ratio_multiply.verify.cpp
new file mode 100644
index 00000000000000..15d118c6d482a5
--- /dev/null
+++ b/libcxx/test/std/utilities/ratio/ratio.arithmetic/ratio_multiply.verify.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <ratio>
+//
+// [ratio.general]/2
+//   Throughout subclause [ratio], the names of template parameters are
+//   used to express type requirements. If a template parameter is named
+//   R1 or R2, and the template argument is not a specialization of the
+//   ratio template, the program is ill-formed.
+
+#include <ratio>
+
+struct invalid {
+  constexpr static int num = 1;
+  constexpr static int den = 1;
+};
+
+using valid = std::ratio<1, 1>;
+
+namespace add {
+using valid_valid = std::ratio_add<valid, valid>::type;
+using invalid_valid =
+    std::ratio_add<invalid, valid>::type; // expected-error@*:* {{R1 to be a specialication of the ratio template}}
+using valid_invalid =
+    std::ratio_add<valid, invalid>::type; // expected-error@*:* {{R2 to be a specialication of the ratio template}}
+} // namespace add
+
+namespace subtract {
+using valid_valid = std::ratio_subtract<valid, valid>::type;
+using invalid_valid =
+    std::ratio_subtract<invalid, valid>::type; // expected-error@*:* {{R1 to be a specialication of the ratio template}}
+using valid_invalid =
+    std::ratio_subtract<valid, invalid>::type; // expected-error@*:* {{R2 to be a specialication of the ratio template}}
+} // namespace subtract
+
+namespace multiply {
+using valid_valid = std::ratio_multiply<valid, valid>::type;
+using invalid_valid =
+    std::ratio_multiply<invalid, valid>::type; // expected-error@*:* {{R1 to be a specialication of the ratio template}}
+using valid_invalid =
+    std::ratio_multiply<valid, invalid>::type; // expected-error@*:* {{R2 to be a specialication of the ratio template}}
+} // namespace multiply
+
+namespace divide {
+using valid_valid = std::ratio_divide<valid, valid>::type;
+using invalid_valid =
+    std::ratio_divide<invalid, valid>::type; // expected-error@*:* {{R1 to be a specialication of the ratio template}}
+using valid_invalid =
+    std::ratio_divide<valid, invalid>::type; // expected-error@*:* {{R2 to be a specialication of the ratio template}}
+} // namespace divide
diff --git a/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement.verify.cpp b/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement.verify.cpp
index 4371dd99c09fab..49cf576285bfdb 100644
--- a/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement.verify.cpp
+++ b/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement.verify.cpp
@@ -14,52 +14,67 @@
 //   R1 or R2, and the template argument is not a specialization of the
 //   ratio template, the program is ill-formed.
 //
-// Since std::ratio_xxx_v uses the same instantiations only one error
-// will be generated. These values are tested in a separate test.
+// Since all std::ratio_xxx_v variables use the same instantiation, only one
+// error will be generated. These values are tested in a separate test.
 
 #include <ratio>
 
-struct R {
+struct invalid {
   static const int num = 1;
   static const int den = 1;
 };
 
-using r = std::ratio<1, 1>;
+using valid = std::ratio<1, 1>;
 
 namespace equal {
-using r_r = std::ratio_equal<r, r>::type;
-using R_r = std::ratio_equal<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-using r_R = std::ratio_equal<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+using valid_valid = std::ratio_equal<valid, valid>::type;
+using invalid_valid =
+    std::ratio_equal<invalid, valid>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using valid_invalid =
+    std::ratio_equal<valid, invalid>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 } // namespace equal
 
 namespace not_equal {
-using r_r = std::ratio_not_equal<r, r>::type;
-using R_r = std::ratio_not_equal<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-using r_R = std::ratio_not_equal<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+using valid_valid = std::ratio_not_equal<valid, valid>::type;
+using invalid_valid = std::ratio_not_equal<invalid,
+                                 valid>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using valid_invalid =
+    std::ratio_not_equal<valid,
+                         invalid>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 } // namespace not_equal
 
 namespace less {
-using r_r = std::ratio_less<r, r>::type;
-using R_r = std::ratio_less<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-using r_R = std::ratio_less<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+using valid_valid = std::ratio_less<valid, valid>::type;
+using invalid_valid =
+    std::ratio_less<invalid, valid>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using valid_invalid =
+    std::ratio_less<valid, invalid>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 } // namespace less
 
 namespace less_equal {
-using r_r = std::ratio_less_equal<r, r>::type;
-using R_r = std::ratio_less_equal<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-using r_R = std::ratio_less_equal<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+using valid_valid = std::ratio_less_equal<valid, valid>::type;
+using invalid_valid =
+    std::ratio_less_equal<invalid,
+                          valid>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using valid_invalid =
+    std::ratio_less_equal<valid,
+                          invalid>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 } // namespace less_equal
 
 namespace greater {
-using r_r = std::ratio_greater<r, r>::type;
-using R_r = std::ratio_greater<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-using r_R = std::ratio_greater<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+using valid_valid = std::ratio_greater<valid, valid>::type;
+using invalid_valid =
+    std::ratio_greater<invalid, valid>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using valid_invalid =
+    std::ratio_greater<valid, invalid>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 } // namespace greater
 
 namespace greater_equal {
-using r_r = std::ratio_greater_equal<r, r>::type;
-using R_r =
-    std::ratio_greater_equal<R, r>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-using r_R =
-    std::ratio_greater_equal<r, R>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+using valid_valid = std::ratio_greater_equal<valid, valid>::type;
+using invalid_valid =
+    std::ratio_greater_equal<invalid,
+                             valid>::type; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+using valid_invalid =
+    std::ratio_greater_equal<valid,
+                             invalid>::type; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 } // namespace greater_equal
diff --git a/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement_v.verify.cpp b/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement_v.verify.cpp
index d30318249c6614..2bcfda13706fee 100644
--- a/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement_v.verify.cpp
+++ b/libcxx/test/std/utilities/ratio/ratio.comparison/R1_R2_requirement_v.verify.cpp
@@ -16,62 +16,54 @@
 //   R1 or R2, and the template argument is not a specialization of the
 //   ratio template, the program is ill-formed.
 //
-// Since std::ratio_xxx uses the same instantiations only one error
-// will be generated. These types are tested in a separate test.
+// Since all std::ratio_xxx_v variables use the same instantiation, only one
+// error will be generated. These values are tested in a separate test.
 
 #include <ratio>
 
-struct R {
+struct invalid {
   constexpr static int num = 1;
   constexpr static int den = 1;
 };
 
-using r = std::ratio<1, 1>;
+using valid = std::ratio<1, 1>;
 
-namespace equal {
-constexpr bool r_r_v = std::ratio_equal_v<r, r>;
-constexpr bool R_r_v =
-    std::ratio_equal_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-constexpr bool r_R_v =
-    std::ratio_equal_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
-} // namespace equal
+void test() {
+  // equal
+  (void)std::ratio_equal_v<valid, valid>;
+  (void)std::ratio_equal_v<invalid, valid>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+  (void)std::ratio_equal_v<valid, invalid>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 
-namespace not_equal {
-constexpr bool r_r_v = std::ratio_not_equal_v<r, r>;
-constexpr bool R_r_v =
-    std::ratio_not_equal_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-constexpr bool r_R_v =
-    std::ratio_not_equal_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
-} // namespace not_equal
+  // not_equal
+  (void)std::ratio_not_equal_v<valid, valid>;
+  (void)std::ratio_not_equal_v<invalid,
+                               valid>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+  (void)std::ratio_not_equal_v<valid,
+                               invalid>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 
-namespace less {
-constexpr bool r_r_v = std::ratio_less_v<r, r>;
-constexpr bool R_r_v =
-    std::ratio_less_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-constexpr bool r_R_v =
-    std::ratio_less_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
-} // namespace less
+  // less
+  (void)std::ratio_less_v<valid, valid>;
+  (void)std::ratio_less_v<invalid, valid>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+  (void)std::ratio_less_v<valid, invalid>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 
-namespace less_equal {
-constexpr bool r_r_v = std::ratio_less_equal_v<r, r>;
-constexpr bool R_r_v =
-    std::ratio_less_equal_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-constexpr bool r_R_v =
-    std::ratio_less_equal_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
-} // namespace less_equal
+  // less_equal
+  (void)std::ratio_less_equal_v<valid, valid>;
+  (void)std::ratio_less_equal_v<invalid,
+                                valid>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+  (void)std::ratio_less_equal_v<valid,
+                                invalid>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 
-namespace greater {
-constexpr bool r_r_v = std::ratio_greater_v<r, r>;
-constexpr bool R_r_v =
-    std::ratio_greater_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-constexpr bool r_R_v =
-    std::ratio_greater_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
-} // namespace greater
+  // greater
+  (void)std::ratio_greater_v<valid, valid>;
+  (void)std::ratio_greater_v<invalid, valid>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+  (void)std::ratio_greater_v<valid, invalid>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
 
-namespace greater_equal {
-constexpr bool r_r_v = std::ratio_greater_equal_v<r, r>;
-constexpr bool R_r_v =
-    std::ratio_greater_equal_v<R, r>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
-constexpr bool r_R_v =
-    std::ratio_greater_equal_v<r, R>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
-} // namespace greater_equal
+  // greater_equal
+  (void)std::ratio_greater_equal_v<valid, valid>;
+
+  (void)std::ratio_greater_equal_v<invalid,
+                                   valid>; // expected-error@*:* {{R1 to be a specialisation of the ratio template}}
+
+  (void)std::ratio_greater_equal_v<valid,
+                                   invalid>; // expected-error@*:* {{R2 to be a specialisation of the ratio template}}
+}



More information about the libcxx-commits mailing list