Skip to content

[libc++] Fix unexpected heterogeneous comparison #115249

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 7, 2024

Conversation

frederick-vs-ja
Copy link
Contributor

@frederick-vs-ja frederick-vs-ja commented Nov 7, 2024

Currently, libc++ incorrectly rejects heterogeneous comparison of unexpected, because the operator== is only a hidden friend of unexpected<_Err> but not of unexpected<_Err2>. We need to call the error() member function on __y.

Fixes #115326

@frederick-vs-ja frederick-vs-ja requested a review from a team as a code owner November 7, 2024 02:14
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Nov 7, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 7, 2024

@llvm/pr-subscribers-libcxx

Author: A. Jiang (frederick-vs-ja)

Changes

Currently, libc++ incorrectly rejects heterogeneous comparison of unexpected, because the operator== is only a hidden friend of unexpected&lt;_Err&gt; but not of unexpected&lt;_Err2&gt;. We need to call the error() member function on __y.

Originally discovered by @Quuxplusone. Fixes Quuxplusone/llvm-project#40.


Full diff: https://github.com/llvm/llvm-project/pull/115249.diff

2 Files Affected:

  • (modified) libcxx/include/__expected/unexpected.h (+1-1)
  • (modified) libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp (+13)
diff --git a/libcxx/include/__expected/unexpected.h b/libcxx/include/__expected/unexpected.h
index c7fe3c52e43114..cf110bcf69a827 100644
--- a/libcxx/include/__expected/unexpected.h
+++ b/libcxx/include/__expected/unexpected.h
@@ -108,7 +108,7 @@ class unexpected {
 
   template <class _Err2>
   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const unexpected& __x, const unexpected<_Err2>& __y) {
-    return __x.__unex_ == __y.__unex_;
+    return __x.__unex_ == __y.error();
   }
 
 private:
diff --git a/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp b/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp
index 3c29cf97580460..7098ffc22c5dab 100644
--- a/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp
+++ b/libcxx/test/std/utilities/expected/expected.unexpected/equality.pass.cpp
@@ -23,15 +23,28 @@
 struct Error{
   int i;
   friend constexpr bool operator==(const Error&, const Error&) = default;
+  friend constexpr bool operator==(const Error& lhs, int rhs) noexcept {
+    return lhs.i == rhs;
+  }
 };
 
 constexpr bool test() {
   std::unexpected<Error> unex1(Error{2});
   std::unexpected<Error> unex2(Error{3});
   std::unexpected<Error> unex3(Error{2});
+
   assert(unex1 == unex3);
   assert(unex1 != unex2);
   assert(unex2 != unex3);
+
+  std::unexpected<int> unex_i1(1);
+  std::unexpected<int> unex_i2(2);
+
+  assert(unex1 != unex_i1);
+  assert(unex_i1 != unex1);
+  assert(unex1 == unex_i2);
+  assert(unex_i2 == unex1);
+
   return true;
 }
 

Copy link

github-actions bot commented Nov 7, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Currently, libc++ incorrectly rejects heterogeneous comparison of
`unexpected`, because the `operator==` is only a hidden friend of
`unexpected<_Err>` but not of `unexpected<_Err2>`. We need to call the
`error()` member function on `__y`.
@ldionne
Copy link
Member

ldionne commented Nov 7, 2024

Just as a matter of process: I created an issue inside LLVM to track this bug, as we should strive to track everything within the boundary of LLVM. In particular, in accordance with https://llvm.org/docs/DeveloperPolicy.html#bans, it's important to take full ownership of a contribution when said contribution comes from a banned individual, and to not proxy communication for that individual (this didn't happen here, but I'm just writing it down to make sure everyone's aware of the policy).

Taking ownership of the issue is what I did by creating #115326: although it was inspired from another issue, it's mine to handle now and I won't be going back to the originator for questions or whatever. This is also not mutually exclusive with attributing contributions, as you can see I linked back to where the inspiration for #115326 came from.

To be clear, you didn't do anything wrong. I'm just clarifying what the process is when a contribution comes from an individual affected by a LLVM ban, to make sure nobody violates the developer policy (perhaps without even knowing it).

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix LGTM, thanks for fixing!

@ldionne ldionne merged commit 9fd3c41 into llvm:main Nov 7, 2024
64 checks passed
@frederick-vs-ja frederick-vs-ja deleted the unexpected-hetero-cmp branch November 7, 2024 17:29
Groverkss pushed a commit to iree-org/llvm-project that referenced this pull request Nov 15, 2024
Currently, libc++ incorrectly rejects heterogeneous comparison of
`unexpected`, because the `operator==` is only a hidden friend of
`unexpected<_Err>` but not of `unexpected<_Err2>`. We need to call the
`error()` member function on `__y`.

Fixes llvm#115326
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc++] Rejects-valid on unexpected(1) == unexpected(1L)
4 participants