Skip to content

[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

Closed
wants to merge 1 commit into from

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Jan 30, 2024

As a drive-by change, also fix a name that wasn't uglified in the code and add a test for that.

Fixes #78754

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
@ldionne ldionne requested a review from a team as a code owner January 30, 2024 15:33
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jan 30, 2024
@llvmbot
Copy link
Member

llvmbot commented Jan 30, 2024

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

As 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:

  • (modified) libcxx/include/scoped_allocator (+16-12)
  • (modified) libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.cnstr/allocs.pass.cpp (+13-1)
  • (added) libcxx/test/std/utilities/allocator.adaptor/base-is-uglified.compile.pass.cpp (+27)
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

Copy link
Member

@mordante mordante left a 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 {};
Copy link
Member

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.

@ldionne
Copy link
Member Author

ldionne commented Feb 5, 2024

@mordante No worries, I've split up the drive-by change into #80706.

@ldionne
Copy link
Member Author

ldionne commented Feb 5, 2024

I'm abandoning this in favour of #80261

@ldionne ldionne closed this Feb 5, 2024
@ldionne ldionne deleted the review/pmr-ambiguity branch February 5, 2024 16:42
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.

[libc++] scoped_allocator_adaptor(Convertible, Convertible) shouldn't be ambiguous
3 participants