Skip to content

Commit bc071fc

Browse files
committed
[libc++] Update polymorphic_allocator to never contain a nullptr
1 parent d86c63d commit bc071fc

File tree

5 files changed

+79
-29
lines changed

5 files changed

+79
-29
lines changed

libcxx/include/__memory_resource/polymorphic_allocator.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ class _LIBCPP_AVAILABILITY_PMR polymorphic_allocator {
5050

5151
_LIBCPP_HIDE_FROM_ABI polymorphic_allocator() noexcept : __res_(std::pmr::get_default_resource()) {}
5252

53-
_LIBCPP_HIDE_FROM_ABI polymorphic_allocator(memory_resource* __r) noexcept : __res_(__r) {}
53+
_LIBCPP_HIDE_FROM_ABI polymorphic_allocator(memory_resource* _LIBCPP_DIAGNOSE_NULLPTR __r) noexcept : __res_(__r) {
54+
_LIBCPP_ASSERT_NON_NULL(__r, "Attempted to pass a nullptr resource to polymorphic_alloator");
55+
}
5456

5557
_LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator&) = default;
5658

@@ -174,7 +176,7 @@ class _LIBCPP_AVAILABILITY_PMR polymorphic_allocator {
174176
return polymorphic_allocator();
175177
}
176178

177-
_LIBCPP_HIDE_FROM_ABI memory_resource* resource() const noexcept { return __res_; }
179+
[[__gnu__::__returns_nonnull__]] _LIBCPP_HIDE_FROM_ABI memory_resource* resource() const noexcept { return __res_; }
178180

179181
_LIBCPP_HIDE_FROM_ABI friend bool
180182
operator==(const polymorphic_allocator& __lhs, const polymorphic_allocator& __rhs) noexcept {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// <memory_resource>
10+
11+
// Test hardening assertions for std::pmr::polymorphic_allocator.
12+
13+
// REQUIRES: has-unix-headers
14+
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
15+
// UNSUPPORTED: c++03, c++11, c++14
16+
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
17+
18+
// We're testing nullptr assertions
19+
// ADDITIONAL_COMPILE_FLAGS: -Wno-nonnull
20+
21+
#include <memory_resource>
22+
23+
#include "check_assertion.h"
24+
25+
int main(int, char**) {
26+
TEST_LIBCPP_ASSERT_FAILURE(
27+
std::pmr::polymorphic_allocator<int>(nullptr), "Attempted to pass a nullptr resource to polymorphic_alloator");
28+
29+
return 0;
30+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14
10+
11+
// Ensure that passing a nullptr to polymorphic_alloator is diagnosed
12+
13+
#include <memory_resource>
14+
15+
void test() {
16+
std::pmr::polymorphic_allocator<int> alloc(nullptr); // expected-warning {{null passed}}
17+
}

libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/resource.pass.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,39 @@
1717
// memory_resource *
1818
// polymorphic_allocator<T>::resource() const
1919

20-
#include <memory_resource>
2120
#include <cassert>
21+
#include <cstddef>
22+
#include <memory_resource>
23+
#include <new>
2224

2325
#include "test_macros.h"
2426

27+
struct resource : std::pmr::memory_resource {
28+
void* do_allocate(size_t, size_t) override { TEST_THROW(std::bad_alloc()); }
29+
void do_deallocate(void*, size_t, size_t) override { assert(false); }
30+
bool do_is_equal(const std::pmr::memory_resource&) const noexcept override { return false; }
31+
};
32+
2533
int main(int, char**) {
2634
typedef std::pmr::polymorphic_allocator<void> A;
2735
{
2836
A const a;
2937
ASSERT_SAME_TYPE(decltype(a.resource()), std::pmr::memory_resource*);
3038
}
3139
{
32-
std::pmr::memory_resource* mptr = (std::pmr::memory_resource*)42;
33-
A const a(mptr);
34-
assert(a.resource() == mptr);
35-
}
36-
{
37-
A const a(nullptr);
38-
assert(a.resource() == nullptr);
39-
assert(a.resource() == nullptr);
40+
resource res;
41+
A const a(&res);
42+
assert(a.resource() == &res);
4043
}
4144
{
4245
A const a;
4346
assert(a.resource() == std::pmr::get_default_resource());
4447
}
4548
{
46-
std::pmr::memory_resource* mptr = (std::pmr::memory_resource*)42;
47-
std::pmr::set_default_resource(mptr);
49+
resource res;
50+
std::pmr::set_default_resource(&res);
4851
A const a;
49-
assert(a.resource() == mptr);
52+
assert(a.resource() == &res);
5053
assert(a.resource() == std::pmr::get_default_resource());
5154
}
5255

libcxx/test/std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/select_on_container_copy_construction.pass.cpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,32 @@
1717
// polymorphic_allocator
1818
// polymorphic_allocator<T>::select_on_container_copy_construction() const
1919

20-
#include <memory_resource>
2120
#include <cassert>
21+
#include <cstddef>
22+
#include <memory_resource>
23+
#include <new>
2224

2325
#include "test_macros.h"
2426

27+
struct resource : std::pmr::memory_resource {
28+
void* do_allocate(size_t, size_t) override { TEST_THROW(std::bad_alloc()); }
29+
void do_deallocate(void*, size_t, size_t) override { assert(false); }
30+
bool do_is_equal(const std::pmr::memory_resource&) const noexcept override { return false; }
31+
};
32+
2533
int main(int, char**) {
2634
typedef std::pmr::polymorphic_allocator<void> A;
2735
{
2836
A const a;
2937
ASSERT_SAME_TYPE(decltype(a.select_on_container_copy_construction()), A);
3038
}
3139
{
32-
std::pmr::memory_resource* mptr = (std::pmr::memory_resource*)42;
33-
A const a(mptr);
34-
assert(a.resource() == mptr);
35-
A const other = a.select_on_container_copy_construction();
36-
assert(other.resource() == std::pmr::get_default_resource());
37-
assert(a.resource() == mptr);
38-
}
39-
{
40-
std::pmr::memory_resource* mptr = (std::pmr::memory_resource*)42;
41-
std::pmr::set_default_resource(mptr);
42-
A const a(nullptr);
43-
assert(a.resource() == nullptr);
40+
resource res;
41+
A const a(&res);
42+
assert(a.resource() == &res);
4443
A const other = a.select_on_container_copy_construction();
4544
assert(other.resource() == std::pmr::get_default_resource());
46-
assert(other.resource() == mptr);
47-
assert(a.resource() == nullptr);
45+
assert(a.resource() == &res);
4846
}
4947

5048
return 0;

0 commit comments

Comments
 (0)