From 0e5104fc323aafd84ff1ceb984dcd8958f30704c Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Sat, 15 Feb 2025 11:34:25 +0100 Subject: [PATCH] [libc++] Further constrain comparison against foo_ordering types This fixes an issue reported in #79465. --- libcxx/include/__compare/ordering.h | 5 ++ .../reject-other-than-literal-zero.verify.cpp | 47 +++++++++++++++---- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/libcxx/include/__compare/ordering.h b/libcxx/include/__compare/ordering.h index 902ef5329dd43..d8fffeda40000 100644 --- a/libcxx/include/__compare/ordering.h +++ b/libcxx/include/__compare/ordering.h @@ -49,6 +49,11 @@ struct _CmpUnspecifiedParam { { (void)__zero; } + + // Reject any other type and reject int lvalues. + template + _CmpUnspecifiedParam(T&&) = delete; + _CmpUnspecifiedParam(const volatile int&) = delete; }; class partial_ordering { diff --git a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp index b6bc4dd4f097a..d86bc418685e2 100644 --- a/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp +++ b/libcxx/test/std/language.support/cmp/cmp.categories.pre/reject-other-than-literal-zero.verify.cpp @@ -22,22 +22,33 @@ #include "test_macros.h" +struct AnyType { + operator int() const { return 0; } +}; + #define TEST_FAIL(v, op) \ do { \ /* invalid types */ \ + constexpr AnyType t; \ void(v op 0L); \ void(0L op v); \ void(v op 0.0); \ void(0.0 op v); \ void(v op nullptr); \ void(nullptr op v); \ + void(v op t); \ + void(t op v); \ /* invalid value */ \ void(v op 1); \ void(1 op v); \ - /* value not known at compile-time */ \ + /* lvalue reference (also, value is not known at compile-time) */ \ int i = 0; \ void(v op i); \ void(i op v); \ + /* value known at compile time, but still a lvalue */ \ + constexpr int j = 0; \ + void(v op j); \ + void(j op v); \ } while (false) #define TEST_PASS(v, op) \ @@ -50,13 +61,33 @@ template void test_category(T v) { - TEST_FAIL(v, ==); // expected-error 30 {{invalid operands to binary expression}} - TEST_FAIL(v, !=); // expected-error 30 {{invalid operands to binary expression}} - TEST_FAIL(v, <); // expected-error 30 {{invalid operands to binary expression}} - TEST_FAIL(v, <=); // expected-error 30 {{invalid operands to binary expression}} - TEST_FAIL(v, >); // expected-error 30 {{invalid operands to binary expression}} - TEST_FAIL(v, >=); // expected-error 30 {{invalid operands to binary expression}} - TEST_FAIL(v, <=>); // expected-error 30 {{invalid operands to binary expression}} + TEST_FAIL(v, ==); + // expected-error-re@-1 36 {{conversion function from '{{.+}}' to '_CmpUnspecifiedParam' invokes a deleted function}} + // expected-error-re@-2 6 {{conversion from '{{.+}}' to '_CmpUnspecifiedParam' is ambiguous}} + + TEST_FAIL(v, !=); + // expected-error-re@-1 36 {{conversion function from '{{.+}}' to '_CmpUnspecifiedParam' invokes a deleted function}} + // expected-error-re@-2 6 {{conversion from '{{.+}}' to '_CmpUnspecifiedParam' is ambiguous}} + + TEST_FAIL(v, <); + // expected-error-re@-1 36 {{conversion function from '{{.+}}' to '_CmpUnspecifiedParam' invokes a deleted function}} + // expected-error-re@-2 6 {{conversion from '{{.+}}' to '_CmpUnspecifiedParam' is ambiguous}} + + TEST_FAIL(v, <=); + // expected-error-re@-1 36 {{conversion function from '{{.+}}' to '_CmpUnspecifiedParam' invokes a deleted function}} + // expected-error-re@-2 6 {{conversion from '{{.+}}' to '_CmpUnspecifiedParam' is ambiguous}} + + TEST_FAIL(v, >); + // expected-error-re@-1 36 {{conversion function from '{{.+}}' to '_CmpUnspecifiedParam' invokes a deleted function}} + // expected-error-re@-2 6 {{conversion from '{{.+}}' to '_CmpUnspecifiedParam' is ambiguous}} + + TEST_FAIL(v, >=); + // expected-error-re@-1 36 {{conversion function from '{{.+}}' to '_CmpUnspecifiedParam' invokes a deleted function}} + // expected-error-re@-2 6 {{conversion from '{{.+}}' to '_CmpUnspecifiedParam' is ambiguous}} + + TEST_FAIL(v, <=>); + // expected-error-re@-1 36 {{conversion function from '{{.+}}' to '_CmpUnspecifiedParam' invokes a deleted function}} + // expected-error-re@-2 6 {{conversion from '{{.+}}' to '_CmpUnspecifiedParam' is ambiguous}} TEST_PASS(v, ==); TEST_PASS(v, !=);