-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++][vector] Make constructor vector(count, value, allocator) exception-safe #82033
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
base: main
Are you sure you want to change the base?
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write If you have received no comments on your PR for a week, you can request a review If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-libcxx Author: Mateusz Zych (mtezych) ChangesThe constructor Since all constructors filling
have nearly identical implementation, their definitions should be physically close to each other. In order to achieve that goal, the constructor
Full diff: https://github.com/llvm/llvm-project/pull/82033.diff 1 Files Affected:
diff --git a/libcxx/include/vector b/libcxx/include/vector
index ce7df7a9f04207..62d36d9318bd69 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -429,15 +429,9 @@ public:
#endif
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(size_type __n, const value_type& __x);
- template <class = __enable_if_t<__is_allocator<_Allocator>::value> >
+ template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
- vector(size_type __n, const value_type& __x, const allocator_type& __a)
- : __end_cap_(nullptr, __a) {
- if (__n > 0) {
- __vallocate(__n);
- __construct_at_end(__n, __x);
- }
- }
+ vector(size_type __n, const value_type& __x, const allocator_type& __a);
template <class _InputIterator,
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
@@ -1165,6 +1159,19 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, con
__guard.__complete();
}
+template <class _Tp, class _Allocator>
+template <__enable_if_t<__is_allocator<_Allocator>::value, int>>
+_LIBCPP_CONSTEXPR_SINCE_CXX20
+vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x, const allocator_type& __a)
+ : __end_cap_(nullptr, __a) {
+ auto __guard = std::__make_exception_guard(__destroy_vector(*this));
+ if (__n > 0) {
+ __vallocate(__n);
+ __construct_at_end(__n, __x);
+ }
+ __guard.__complete();
+}
+
template <class _Tp, class _Allocator>
template <class _InputIterator,
__enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
|
Please don't move the code outside the class definition. We try to move away from that. |
OK, so you would prefer me to define all constructors filling Notice that, you forgot to add the exception guard in the commit 8ff4d21, |
I'd prefer to keep the bug fix and moving code separate. If you want to move the code, feel free to open a new PR. The code being defined in two different places being the reason seems like wild speculation to me. I'm pretty sure I went through the constructors on cppreference. Much more importantly: please add a test case for your change. Since you referenced my patch to fix most places, I think you should have a good idea of what to do. If you need any help feel free to ask here or on discord. |
Sure, I've created new pull request #82068 with the change that I hope that placing those constructors physically next to each other Regarding the unit-tests, yes, of course, I agree that all changes fixing bugs I even tried to extend your tests //libcxx/test/std/containers/sequences/vector/vector.cons/exceptions.pass.cpp, However, these exception safety tests covering constructors of
In my opinion the above issues need to be resolved first, then the test cases covering this bug fix can be added. I am perfectly happy to do so, but this will require rewriting almost the whole exceptions.pass.cpp source file, |
8bb3129
to
7ff58b5
Compare
As the comment in the test says, it's there to make sure that throwing in the constructors doesn't leak memory. It was never meant to check that all the correct destructors were run. If you want to take up the effort to improve the test coverage of exceptions in the Regarding what exactly to do, I think it would be good to first fix You can use any extensions that Clang provides in C++03. |
@mtezych Do you still have interest for finishing this patch? |
This is going to have to slip to the next release. |
The constructor
std::vector(count, value, allocator)
was missing an exception guard,responsible for destroying successfully created elements, in case an exception was thrown:
Since all constructors filling
std::vector<>
with elements of the same value:vector(count)
vector(count, allocator)
vector(count, value)
vector(count, value, allocator)
have nearly identical implementation, their definitions should be physically close to each other.
In order to achieve that goal, the constructor
std::vector(count, value, allocator)
is now definedoutside of the
std::vector<>
class template and has sightly differentenable_if<>
expression,matching to those used in the constructors taking two iterators:
vector(iterator first, iterator last)
vector(iterator first, iterator last, allocator)