]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Do not cast away const-ness in std::construct_at (LWG 3870)
authorJonathan Wakely <jwakely@redhat.com>
Thu, 11 Jul 2024 19:38:05 +0000 (20:38 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 9 Oct 2024 12:39:15 +0000 (13:39 +0100)
This change also requires implementing the proposed resolution of LWG
3216 so that std::make_shared and std::allocate_shared still work, and
the proposed resolution of LWG 3891 so that std::expected still works.

libstdc++-v3/ChangeLog:

* include/bits/shared_ptr_base.h: Remove cv-qualifiers from
type managed by _Sp_counted_ptr_inplace, as per LWG 3210.
* include/bits/stl_construct.h: Do not cast away cv-qualifiers
when passing pointer to placement new.
* include/std/expected: Use remove_cv_t for union member, as per
LWG 3891.
* testsuite/20_util/allocator/void.cc: Do not test construction
via const pointer.

libstdc++-v3/include/bits/shared_ptr_base.h
libstdc++-v3/include/bits/stl_construct.h
libstdc++-v3/include/std/expected
libstdc++-v3/testsuite/20_util/allocator/void.cc

index 3d0b74ba1c6eea23bdece8eb881015d2816dd74c..ef0658f61828959cb940d5253fbd578ac138cb72 100644 (file)
@@ -591,7 +591,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
        _Alloc& _M_alloc() noexcept { return _A_base::_S_get(*this); }
 
-       __gnu_cxx::__aligned_buffer<_Tp> _M_storage;
+       __gnu_cxx::__aligned_buffer<__remove_cv_t<_Tp>> _M_storage;
       };
 
     public:
@@ -633,7 +633,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       virtual void*
       _M_get_deleter(const std::type_info& __ti) noexcept override
       {
-       auto __ptr = const_cast<typename remove_cv<_Tp>::type*>(_M_ptr());
        // Check for the fake type_info first, so we don't try to access it
        // as a real type_info object. Otherwise, check if it's the real
        // type_info for this class. With RTTI enabled we can check directly,
@@ -646,11 +645,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            _Sp_make_shared_tag::_S_eq(__ti)
 #endif
           )
-         return __ptr;
+         return _M_ptr();
        return nullptr;
       }
 
-      _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
+      __remove_cv_t<_Tp>*
+      _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
 
       _Impl _M_impl;
     };
@@ -674,13 +674,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       [[no_unique_address]] _Alloc _M_alloc;
 
       union {
-       _Tp _M_obj;
+       remove_cv_t<_Tp> _M_obj;
        char _M_unused;
       };
 
       friend class __shared_count<_Lp>; // To be able to call _M_ptr().
 
-      _Tp* _M_ptr() noexcept { return std::__addressof(_M_obj); }
+      auto _M_ptr() noexcept { return std::__addressof(_M_obj); }
 
     public:
       using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
@@ -962,7 +962,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
                       _Args&&... __args)
        {
-         typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
+         using _Tp2 = __remove_cv_t<_Tp>;
+         using _Sp_cp_type = _Sp_counted_ptr_inplace<_Tp2, _Alloc, _Lp>;
          typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
          auto __guard = std::__allocate_guarded(__a2);
          _Sp_cp_type* __mem = __guard.get();
index 146ea14e99ad94ad45d5061fcad41eedfa00802c..9d6111396e1ce60577b5631e98a893bd49744cf7 100644 (file)
@@ -96,7 +96,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     construct_at(_Tp* __location, _Args&&... __args)
     noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...)))
     {
-      void* __loc = const_cast<remove_cv_t<_Tp>*>(__location);
+      void* __loc = __location;
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // 3436. std::construct_at should support arrays
       if constexpr (is_array_v<_Tp>)
@@ -130,7 +130,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          return;
        }
 #endif
-      ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
+      ::new(static_cast<void*>(__p)) _Tp(std::forward<_Args>(__args)...);
     }
 #else
   template<typename _T1, typename _T2>
@@ -146,7 +146,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _T1>
     inline void
     _Construct_novalue(_T1* __p)
-    { ::new((void*)__p) _T1; }
+    { ::new(static_cast<void*>(__p)) _T1; }
 
   template<typename _ForwardIterator>
     _GLIBCXX20_CONSTEXPR void
index 9e92339e4066e5bbc0444c4e94774d3eb90610c8..d4a4bc17541510ef52cbb364a2d85ef7e13e2190 100644 (file)
@@ -1261,7 +1261,7 @@ namespace __expected
        { }
 
       union {
-       _Tp _M_val;
+       remove_cv_t<_Tp> _M_val;
        _Er _M_unex;
       };
 
index e50bf9932948d7b3b9064082490cf116ca633ec9..04cd2094776a02d7a69d27bbf167f11dd53b4c25 100644 (file)
@@ -88,23 +88,8 @@ static_assert( std::is_same<std::allocator<void>::const_pointer, const void*>(),
     "const_pointer is const void*" );
 #endif // C++20
 
-void
-test02()
-{
-  std::allocator<void> av;
-  int* p = std::allocator<int>().allocate(1);
-  const int* c = p;
-  std::allocator_traits<std::allocator<void>>::construct(av, c, 0);
-  volatile int* v = p;
-  std::allocator_traits<std::allocator<void>>::construct(av, v, 0);
-  const volatile int* cv = p;
-  std::allocator_traits<std::allocator<void>>::construct(av, cv, 0);
-  std::allocator<int>().deallocate(p, 1);
-}
-
 int
 main()
 {
   test01();
-  test02();
 }