Allow __move_constexpr to work with unrelated pointers and _LIBCPP_ASSERT that __copy_constexpr, __move_constexpr and __assign_constexpr are only run during constant evaluation
Details
- Reviewers
• Quuxplusone ldionne - Group Reviewers
Restricted Project - Commits
- rGedb46980081c: [libc++] Allow __move_constexpr to work with unrelated pointers
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
FWIW, I'm a little leery of how we're making these codepaths more and more complicated. If it wouldn't merge-conflict horribly with the "constexpr std::string" stuff, I would be very tempted to take a close look at all of these codepaths and see how they could be simplified.
For example, __copy_constexpr is an overload set: there's a __copy_constexpr(T*, T*, size_t) here in <__string> but also a __copy_constexpr(In, In, Out) in <__algorithm/copy.h> (which is tied up with all the __unwrap_iter/__rewrap_iter stuff). We don't need that overload set to exist.
For example, __assign_constexpr and this overload of __copy_constexpr are one-liners; they could probably just be inlined into their three callers.
Orthogonally, consider renaming __s1 and __s2 to __src and __dest respectively (or vice versa).
Orthogonally, I wonder if we're 100% sure that constexpr new and delete (as used here) are fully supported in Clang 13. Libc++ 14 will still have to work with Clang 13.
Feel free to change the __{copy, move, assign}_constexpr functions, as long as you make char_traits::move work with unrelated pointers. They aren't used directly in <string>, so I should be able to just drop the changes in <__string>.
What do you mean "with unrelated pointers"? Can you explain what breaks when you use std::copy to implement __move_constexpr?
The problem isn't std::copy. The problem is __s1 < __s2, which only works if you have two pointers that were derived by __s2 = __s1 + c. Otherwise the constant evaluator will fail, because there is no rule to determine which pointer is larger.
As @Quuxplusone mentions, I would really support an effort to clean up our various __foo_constexpr functions.
LGTM with the renaming.
libcxx/include/__string | ||
---|---|---|
293 | __s1 and __s2 is super confusing, especially since the order is reversed from std::copy_n. Please apply this throughout as a fly-by. | |
295–297 | This is pretty annoying -- if we ever end up calling this function outside of constexpr (by mistake or otherwise), we'll end up with an assertion that fails at runtime. I don't see a way to make this fail at compile-time, since if you use __libcpp_is_constant_evaluated() in a place where a constant expression is required, it'll always return true. There's nothing actionable to this comment, but I thought I'd point out that this is a pretty bad defect of is_constant_evaluated(). |
__s1 and __s2 is super confusing, especially since the order is reversed from std::copy_n. Please apply this throughout as a fly-by.