Skip to content

[libc++] Remove unnecessary static_casts in std::forward_list #130310

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

winner245
Copy link
Contributor

The patch removes unnecessary casts to void* pointers and eliminates an identity cast.

Copy link

github-actions bot commented Mar 7, 2025

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

@winner245 winner245 marked this pull request as ready for review March 7, 2025 22:21
@winner245 winner245 requested a review from a team as a code owner March 7, 2025 22:21
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Mar 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 7, 2025

@llvm/pr-subscribers-libcxx

Author: Peng Liu (winner245)

Changes

The patch removes unnecessary casts to void* pointers and eliminates an identity cast.


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

1 Files Affected:

  • (modified) libcxx/include/forward_list (+5-13)
diff --git a/libcxx/include/forward_list b/libcxx/include/forward_list
index 7582de20995b9..1d1415aaa0e27 100644
--- a/libcxx/include/forward_list
+++ b/libcxx/include/forward_list
@@ -296,7 +296,7 @@ struct __forward_node_traits {
 #  endif
 
   _LIBCPP_HIDE_FROM_ABI static __begin_node_pointer __as_iter_node(__node_pointer __p) {
-    return static_cast<__begin_node_pointer>(static_cast<__void_pointer>(__p));
+    return static_cast<__begin_node_pointer>(__p);
   }
 };
 
@@ -363,12 +363,8 @@ class _LIBCPP_TEMPLATE_VIS __forward_list_iterator {
 
   __begin_node_pointer __ptr_;
 
-  _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const {
-    return static_cast<__begin_node_pointer>(static_cast<__void_pointer>(__ptr_));
-  }
-  _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const {
-    return static_cast<__node_pointer>(static_cast<__void_pointer>(__ptr_));
-  }
+  _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const { return __ptr_; }
+  _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const { return static_cast<__node_pointer>(__ptr_); }
 
   _LIBCPP_HIDE_FROM_ABI explicit __forward_list_iterator(nullptr_t) _NOEXCEPT : __ptr_(nullptr) {}
 
@@ -427,12 +423,8 @@ class _LIBCPP_TEMPLATE_VIS __forward_list_const_iterator {
 
   __begin_node_pointer __ptr_;
 
-  _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const {
-    return static_cast<__begin_node_pointer>(static_cast<__void_pointer>(__ptr_));
-  }
-  _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const {
-    return static_cast<__node_pointer>(static_cast<__void_pointer>(__ptr_));
-  }
+  _LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const { return __ptr_; }
+  _LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const { return static_cast<__node_pointer>(__ptr_); }
 
   _LIBCPP_HIDE_FROM_ABI explicit __forward_list_const_iterator(nullptr_t) _NOEXCEPT : __ptr_(nullptr) {}
 

Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

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

@nico Could you maybe check whether you see any breakage with this change?

Comment on lines 298 to 300
_LIBCPP_HIDE_FROM_ABI static __begin_node_pointer __as_iter_node(__node_pointer __p) {
return static_cast<__begin_node_pointer>(static_cast<__void_pointer>(__p));
return static_cast<__begin_node_pointer>(__p);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should just inline this. That probably makes the code easier to read, since you don't have to guess what __as_iter_node means.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I agree that inlining these short one-liner static_casts makes sense—it doesn’t bloat the code and actually improves readability. For instance, after getting rid of the unnecessary casts, __get_begin() is nothing but a class getter, and inlining _iter.__get_begin() as __iter.__ptr_ makes the code more obvious. So I've inlined all three functions. Additionally, I noticed that __p->__next_as_begin() exactly duplicates the functionality of __as_iter_node(__p->__next_), so I think we can get rid of the function __next_as_begin() entirely. Then we can inline the calls to __next_as_begin() as well (if we choose not to inline __as_iter_node, we can simply replace the __next_as_begin calls by__as_iter_node). I'm not sure if I am doing too much of inlining here (please let me know if you dislike some of the inlining).

Comment on lines 366 to 367
_LIBCPP_HIDE_FROM_ABI __begin_node_pointer __get_begin() const { return __ptr_; }
_LIBCPP_HIDE_FROM_ABI __node_pointer __get_unsafe_node_pointer() const { return static_cast<__node_pointer>(__ptr_); }
Copy link
Contributor

Choose a reason for hiding this comment

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

These probably as well, but I'm a bit less sure about them.

Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

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

LGTM. @ldionne do you have any thoughts?

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.

LGTM

@ldionne
Copy link
Member

ldionne commented Mar 25, 2025

@nico Could you maybe check whether you see any breakage with this change?

Is there a reason why you suspect this might break some code?

@philnik777
Copy link
Contributor

@nico Could you maybe check whether you see any breakage with this change?

Is there a reason why you suspect this might break some code?

Nothing specific. It's mostly that this requires a converting constructor that it didn't before and I wasn't able to find any specifics about fancy pointers in the standard.

@ldionne
Copy link
Member

ldionne commented Mar 26, 2025

Ack. I think this looks fine to me, but we might want to double-check what @frederick-vs-ja thinks about this one. Frederick, I'm also unfamiliar with the requirements on pointer-like types in the standard, and http://eel.is/c++draft/memory is very light on details. Do you know if we're allowed to assume that we can convert between fancy pointer types via conversions that would be legal if we were using raw pointers instead? Such as fancy_pointer<Derived> to fancy_pointer<Base>.

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.

4 participants