//===----------------------------------------------------------------------===//
//
// 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, c++11, c++14, c++17, c++20
// <memory>
// [inout.ptr], function template inout_ptr
// template<class Pointer = void, class Smart, class... Args>
// auto inout_ptr(Smart& s, Args&&... args); // since c++23
#include <cassert>
#include <memory>
#include <utility>
#include "../types.h"
// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type.
// The API returns a new valid object.
void test_replace_int_p() {
auto replace_int_p = [](int** pp) {
assert(**pp == 90);
delete *pp;
*pp = new int{84};
};
// raw pointer
{
auto rPtr = new int{90};
replace_int_p(std::inout_ptr<int*>(rPtr));
assert(*rPtr == 84);
delete rPtr;
}
// std::unique_ptr
{
auto uPtr = std::make_unique<int>(90);
replace_int_p(std::inout_ptr(uPtr));
assert(*uPtr == 84);
}
{
MoveOnlyDeleter<int> del;
std::unique_ptr<int, MoveOnlyDeleter<int>> uPtr{new int{90}};
replace_int_p(std::inout_ptr(uPtr, std::move(del)));
assert(*uPtr == 84);
assert(uPtr.get_deleter().wasMoveInitilized == true);
}
// pointer-like ConstructiblePtr
{
ConstructiblePtr<int> cPtr(new int{90});
replace_int_p(std::inout_ptr(cPtr));
assert(cPtr == 84);
}
// pointer-like ResettablePtr
{
ResettablePtr<int> rPtr(new int{90});
replace_int_p(std::inout_ptr(rPtr));
assert(rPtr == 84);
}
// pointer-like NonConstructiblePtr
{
NonConstructiblePtr<int> nPtr;
nPtr.reset(new int{90});
replace_int_p(std::inout_ptr(nPtr));
assert(nPtr == 84);
}
}
// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type.
// The API returns `nullptr`.
void test_replace_int_p_with_nullptr() {
auto replace_int_p_with_nullptr = [](int** pp) -> void {
assert(**pp == 90);
delete *pp;
*pp = nullptr;
};
// raw pointer
{
// LWG-3897 inout_ptr will not update raw pointer to null
auto rPtr = new int{90};
replace_int_p_with_nullptr(std::inout_ptr<int*>(rPtr));
assert(rPtr == nullptr);
}
// std::unique_ptr
{
auto uPtr = std::make_unique<int>(90);
replace_int_p_with_nullptr(std::inout_ptr(uPtr));
assert(uPtr == nullptr);
}
}
// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a void pointer type.
// The API returns a new valid object.
void test_replace_int_void_p() {
auto replace_int_void_p = [](void** pp) {
assert(*(static_cast<int*>(*pp)) == 90);
delete static_cast<int*>(*pp);
*pp = new int{84};
};
// raw pointer
{
auto rPtr = new int{90};
replace_int_void_p(std::inout_ptr<int*>(rPtr));
assert(*rPtr == 84);
delete rPtr;
}
// std::unique_ptr
{
auto uPtr = std::make_unique<int>(90);
replace_int_void_p(std::inout_ptr(uPtr));
assert(*uPtr == 84);
}
}
// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a non-void pointer type.
// The API returns `nullptr`.
void test_replace_int_void_p_with_nullptr() {
auto replace_int_void_p_with_nullptr = [](void** pp) {
assert(*(static_cast<int*>(*pp)) == 90);
delete static_cast<int*>(*pp);
*pp = nullptr;
};
// raw pointer
{
auto rPtr = new int{90};
replace_int_void_p_with_nullptr(std::inout_ptr<int*>(rPtr));
assert(rPtr == nullptr);
}
// std::unique_ptr
{
auto uPtr = std::make_unique<int>(90);
replace_int_void_p_with_nullptr(std::inout_ptr(uPtr));
assert(uPtr == nullptr);
}
}
// Test updating the ownership of an `inout_ptr_t`-managed pointer for an API with a void pointer type.
// The API returns a new valid object.
void test_replace_nullptr_with_int_p() {
auto replace_nullptr_with_int_p = [](int** pp) {
assert(*pp == nullptr);
*pp = new int{84};
};
// raw pointer
{
int* rPtr = nullptr;
replace_nullptr_with_int_p(std::inout_ptr<int*>(rPtr));
assert(*rPtr == 84);
delete rPtr;
}
// std::unique_ptr
{
std::unique_ptr<int> uPtr;
replace_nullptr_with_int_p(std::inout_ptr(uPtr));
assert(*uPtr == 84);
}
}
int main(int, char**) {
test_replace_int_p();
test_replace_int_p_with_nullptr();
test_replace_int_void_p();
test_replace_int_void_p_with_nullptr();
test_replace_nullptr_with_int_p();
return 0;
}