-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] Fix ambiguity when using std::scoped_allocator constructor #80020
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
Conversation
As a drive-by change, also fix a name that wasn't uglified in the code and add a test for that. Fixes llvm#78754
@llvm/pr-subscribers-libcxx Author: Louis Dionne (ldionne) ChangesAs a drive-by change, also fix a name that wasn't uglified in the code and add a test for that. Fixes #78754 Full diff: https://github.com/llvm/llvm-project/pull/80020.diff 3 Files Affected:
diff --git a/libcxx/include/scoped_allocator b/libcxx/include/scoped_allocator
index 6078906e92248..2d56ae785e5e4 100644
--- a/libcxx/include/scoped_allocator
+++ b/libcxx/include/scoped_allocator
@@ -197,6 +197,8 @@ struct __get_is_always_equal<_A0, _Allocs...> {
static const bool value = allocator_traits<_A0>::is_always_equal::value && __get_is_always_equal<_Allocs...>::value;
};
+struct __chained_ctor_tag {};
+
template <class... _Allocs>
class __scoped_allocator_storage;
@@ -249,6 +251,7 @@ protected:
scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...> _LIBCPP_HIDE_FROM_ABI
select_on_container_copy_construction() const _NOEXCEPT {
return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>(
+ __chained_ctor_tag(),
allocator_traits<outer_allocator_type>::select_on_container_copy_construction(outer_allocator()),
allocator_traits<inner_allocator_type>::select_on_container_copy_construction(inner_allocator()));
}
@@ -334,12 +337,12 @@ struct __outermost<_Alloc, true> {
template <class _OuterAlloc, class... _InnerAllocs>
class _LIBCPP_TEMPLATE_VIS scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>
: public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> {
- typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> base;
+ typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> _Base;
typedef allocator_traits<_OuterAlloc> _OuterTraits;
public:
typedef _OuterAlloc outer_allocator_type;
- typedef typename base::inner_allocator_type inner_allocator_type;
+ typedef typename _Base::inner_allocator_type inner_allocator_type;
typedef typename _OuterTraits::size_type size_type;
typedef typename _OuterTraits::difference_type difference_type;
typedef typename _OuterTraits::pointer pointer;
@@ -365,29 +368,29 @@ public:
template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
scoped_allocator_adaptor(_OuterA2&& __outer_alloc, const _InnerAllocs&... __inner_allocs) _NOEXCEPT
- : base(std::forward<_OuterA2>(__outer_alloc), __inner_allocs...) {}
+ : _Base(std::forward<_OuterA2>(__outer_alloc), __inner_allocs...) {}
// scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) = default;
template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, const _OuterA2&>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
scoped_allocator_adaptor(const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT
- : base(__other) {}
+ : _Base(__other) {}
template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI
scoped_allocator_adaptor(scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT
- : base(std::move(__other)) {}
+ : _Base(std::move(__other)) {}
// scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
// scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default;
// ~scoped_allocator_adaptor() = default;
- _LIBCPP_HIDE_FROM_ABI inner_allocator_type& inner_allocator() _NOEXCEPT { return base::inner_allocator(); }
+ _LIBCPP_HIDE_FROM_ABI inner_allocator_type& inner_allocator() _NOEXCEPT { return _Base::inner_allocator(); }
_LIBCPP_HIDE_FROM_ABI const inner_allocator_type& inner_allocator() const _NOEXCEPT {
- return base::inner_allocator();
+ return _Base::inner_allocator();
}
- _LIBCPP_HIDE_FROM_ABI outer_allocator_type& outer_allocator() _NOEXCEPT { return base::outer_allocator(); }
+ _LIBCPP_HIDE_FROM_ABI outer_allocator_type& outer_allocator() _NOEXCEPT { return _Base::outer_allocator(); }
_LIBCPP_HIDE_FROM_ABI const outer_allocator_type& outer_allocator() const _NOEXCEPT {
- return base::outer_allocator();
+ return _Base::outer_allocator();
}
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_HIDE_FROM_ABI pointer allocate(size_type __n) {
@@ -472,13 +475,14 @@ public:
}
_LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT {
- return base::select_on_container_copy_construction();
+ return _Base::select_on_container_copy_construction();
}
private:
template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
- _LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor(_OuterA2&& __o, const inner_allocator_type& __i) _NOEXCEPT
- : base(std::forward<_OuterA2>(__o), __i) {}
+ _LIBCPP_HIDE_FROM_ABI
+ scoped_allocator_adaptor(__chained_ctor_tag, _OuterA2&& __o, const inner_allocator_type& __i) _NOEXCEPT
+ : _Base(std::forward<_OuterA2>(__o), __i) {}
template <class _Tp, class... _Args>
_LIBCPP_HIDE_FROM_ABI void __construct(integral_constant<int, 0>, _Tp* __p, _Args&&... __args) {
diff --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp
index a752dfd029eff..91dd13e4cd354 100644
--- a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp
+++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp
@@ -17,8 +17,9 @@
// scoped_allocator_adaptor(OuterA2&& outerAlloc,
// const InnerAllocs& ...innerAllocs);
-#include <scoped_allocator>
#include <cassert>
+#include <memory_resource>
+#include <scoped_allocator>
#include "test_macros.h"
#include "allocators.h"
@@ -111,6 +112,17 @@ int main(int, char**) {
!std::is_convertible< std::scoped_allocator_adaptor<A1<int>>, std::scoped_allocator_adaptor<A2<int>>>::value,
"");
}
+ {
+ // https://github.com/llvm/llvm-project/issues/78754
+ using PA = std::pmr::polymorphic_allocator<int>;
+ std::pmr::monotonic_buffer_resource mr1;
+ std::pmr::monotonic_buffer_resource mr2;
+
+ using A = std::scoped_allocator_adaptor<PA, PA>;
+ A a(&mr1, &mr2);
+ assert(a.outer_allocator().resource() == &mr1);
+ assert(a.inner_allocator().resource() == &mr2);
+ }
return 0;
}
diff --git a/libcxx/test/std/utilities/allocator.adaptor/base-is-uglified.compile.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/base-is-uglified.compile.pass.cpp
new file mode 100644
index 0000000000000..af2171b0e234c
--- /dev/null
+++ b/libcxx/test/std/utilities/allocator.adaptor/base-is-uglified.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <memory>
+
+// This test ensures that we don't use a non-uglified name 'base' in the
+// implementation of scoped_allcoator_adaptor.
+//
+// See https://github.com/llvm/llvm-project/issues/78754.
+
+#include <memory>
+#include <scoped_allocator>
+
+using ScopedAlloc = std::scoped_allocator_adaptor<std::allocator<int>, std::allocator<int>>;
+struct MyBase {
+ using base = MyBase;
+};
+struct MyDerived : ScopedAlloc, MyBase {};
+
+using T = MyDerived::base; // Should be well-formed
|
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.
LGTM modulo one comment.
I spend a bit of time hunting for the real changes, I would have preferred to split this in two commits.
@@ -197,6 +197,8 @@ struct __get_is_always_equal<_A0, _Allocs...> { | |||
static const bool value = allocator_traits<_A0>::is_always_equal::value && __get_is_always_equal<_Allocs...>::value; | |||
}; | |||
|
|||
struct __chained_ctor_tag {}; |
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 you add some comment to this tag, preferably referring to the bug it fixes.
I'm abandoning this in favour of #80261 |
As a drive-by change, also fix a name that wasn't uglified in the code and add a test for that.
Fixes #78754