-
Notifications
You must be signed in to change notification settings - Fork 12k
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
[libc++][test] Refactor increasing_allocator #115671
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-libcxx Author: Peng Liu (winner245) ChangesThe > a.allocate(n) This PR addresses the issue by modifying Full diff: https://github.com/llvm/llvm-project/pull/115671.diff 3 Files Affected:
diff --git a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
index f8bcee31964bbb..136b151efa29ef 100644
--- a/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector.bool/shrink_to_fit.pass.cpp
@@ -55,7 +55,7 @@ struct increasing_allocator {
min_elements += 1000;
return std::allocator<T>{}.allocate_at_least(n);
}
- constexpr T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
+ constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
};
diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
index e39afb2d48f0a0..97d67dac2baa8c 100644
--- a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp
@@ -87,7 +87,7 @@ struct increasing_allocator {
min_elements += 1000;
return std::allocator<T>{}.allocate_at_least(n);
}
- constexpr T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
+ constexpr T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
constexpr void deallocate(T* p, std::size_t n) noexcept { std::allocator<T>{}.deallocate(p, n); }
};
diff --git a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
index 6f5e43d1341f53..68360329308bab 100644
--- a/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.capacity/shrink_to_fit.pass.cpp
@@ -79,8 +79,8 @@ struct increasing_allocator {
min_bytes += 1000;
return {static_cast<T*>(::operator new(allocation_amount)), allocation_amount / sizeof(T)};
}
- T* allocate(std::size_t n) { return allocate_at_least(n).ptr; }
- void deallocate(T* p, std::size_t) noexcept { ::operator delete(static_cast<void*>(p)); }
+ T* allocate(std::size_t n) { return std::allocator<T>{}.allocate(n); }
+ void deallocate(T* p, std::size_t) noexcept { std::allocator<T>{}.deallocate(p, n); }
};
template <typename T, typename U>
|
4044fbe
to
3402842
Compare
@@ -55,7 +55,7 @@ struct increasing_allocator { | |||
min_elements += 1000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we factor out the code into a single location?
I feel like the reasoning is backwards here. AFAICT the only problem is that we're mismatching the |
@winner245 Actually, how did you come across this issue? Did our test suite fail with another Standard library somehow? |
Because I just realized that the same issue #95161 applies to I was trying to find a different way to solve the |
I personally do not like the current solution, because |
The intention of |
Actually, the tests failed with MSVC STL (or MSVC, the compiler). MSVC detects size mismatch of deallocation in constant evaluation. I guess we can't reliably perform over allocation in constant evaluation. (It seems that VCRuntime can detect size mismatch at run time.) |
I agree, and I don't see how this makes the allocator more conforming than it used to be. However, I do think the code makes more sense after the patch than it did before the patch, because implementing
constexpr std::allocation_result<T*> allocate_at_least(std::size_t n);
constexpr T* allocate(std::size_t n) {
auto res = allocate_at_least(n);
return res.ptr;
}
constexpr void deallocate(T* p, std::size_t n) noexcept {
// n may be wrong: it must match res.count which may not be the case if we used allocate_at_least above
std::allocator<T>{}.deallocate(p, n);
} Is that what you're saying? I would understand why the current code is a problem in that case, however http://eel.is/c++draft/allocator.members#10.1 says:
In other words, I think it's supposed to be just fine to call |
I'm not disagreeing here. The code is an improvement, but I don't think the commit message makes sense.
The calling code is fine. The mismatch between the Actually, I just noticed that the current code is still wrong, since there is still potentially the same mismatch when calling |
Thank you all for the very informative discussions here. I agree that the current solution for
|
Cpp17Allocator
requirements3402842
to
9d584f7
Compare
The
increasing_allocator<T>
class, originally introduced to testshrink_to_fit
forvector
andstring
(#95161), does not satisfyCpp17Allocator
requirements because itsallocate(n)
member function may allocate more memory than requested. However, the standard ([allocator.requirements]/36) mandates thata.allocate(n)
must allocate memory for an array of exactlyn
objects of typeT
.This PR addresses the issue by modifying
increasing_allocator<T>::allocate(n)
such that it strictly allocates for exactlyn
objects. Note that this change does not affect the existing tests forshrink_to_fit
, as those tests only utilize theallocate_at_least
member function, which is already standard conforming.