//===----------------------------------------------------------------------===//
//
// 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

// <scoped_allocator>

// template <class OtherAlloc, class ...InnerAlloc>
//   class scoped_allocator_adaptor

// template <class T, class ...Args>
// void scoped_allocator_adaptor::construct(T*, Args&&...)

#include <scoped_allocator>
#include <type_traits>
#include <utility>
#include <tuple>
#include <cassert>
#include <cstdlib>
#include "uses_alloc_types.h"
#include "controlled_allocators.h"

#include "test_macros.h"

// - If uses_allocator_v<T, inner_allocator_type> is false and
//   is_constructible_v<T, Args...> is true, calls
//   OUTERMOST_ALLOC_TRAITS(*this)::construct(
//      OUTERMOST (*this), p, std::forward<Args>(args)...).
void test_bullet_one() {
    using VoidAlloc2 = CountingAllocator<void, 2>;

    AllocController POuter;
    AllocController PInner;
    {
        using T = NotUsesAllocator<VoidAlloc2, 3>;
        using Outer = CountingAllocator<T, 1>;
        using Inner = CountingAllocator<T, 2>;
        using SA = std::scoped_allocator_adaptor<Outer, Inner>;
        static_assert(!std::uses_allocator<T, Outer>::value, "");
        static_assert(!std::uses_allocator<T, Inner>::value, "");
        T* ptr = (T*)::operator new(sizeof(T));
        Outer O(POuter);
        Inner I(PInner);
        SA A(O, I);
        int x = 42;
        int const& cx = x;
        A.construct(ptr, x, cx, std::move(x));
        assert((checkConstruct<int&, int const&, int&&>(*ptr, UA_None)));
        assert((POuter.checkConstruct<int&, int const&, int&&>(O, ptr)));
        A.destroy(ptr);
        ::operator delete((void*)ptr);
    }
    PInner.reset();
    POuter.reset();
}


// Otherwise, if uses_allocator_v<T, inner_allocator_type> is true and
// is_constructible_v<T, allocator_arg_t, inner_allocator_type&, Args...> is
// true, calls OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST (*this), p,
//     allocator_arg, inner_allocator(), std::forward<Args>(args)...).
void test_bullet_two() {
    using VoidAlloc2 = CountingAllocator<void, 2>;

    AllocController POuter;
    AllocController PInner;
    {
        using T = UsesAllocatorV1<VoidAlloc2, 3>;
        using Outer = CountingAllocator<T, 1>;
        using Inner = CountingAllocator<T, 2>;
        using SA = std::scoped_allocator_adaptor<Outer, Inner>;
        static_assert(!std::uses_allocator<T, Outer>::value, "");
        static_assert(std::uses_allocator<T, Inner>::value, "");
        T* ptr = (T*)::operator new(sizeof(T));
        Outer O(POuter);
        Inner I(PInner);
        SA A(O, I);
        int x = 42;
        int const& cx = x;
        A.construct(ptr, x, cx, std::move(x));
        assert((checkConstruct<int&, int const&, int&&>(*ptr, UA_AllocArg, I)));
        assert((POuter.checkConstruct<std::allocator_arg_t const&,
                   SA::inner_allocator_type&, int&, int const&, int&&>(O, ptr)));
        A.destroy(ptr);
        ::operator delete((void*)ptr);
    }
    PInner.reset();
    POuter.reset();
}

// Otherwise, if uses_allocator_v<T, inner_allocator_type> is true and
// is_constructible_v<T, Args..., inner_allocator_type&> is true, calls
// OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST (*this), p,
//   std::forward<Args>(args)..., inner_allocator()).
void test_bullet_three() {
    using VoidAlloc2 = CountingAllocator<void, 2>;

    AllocController POuter;
    AllocController PInner;
    {
        using T = UsesAllocatorV2<VoidAlloc2, 3>;
        using Outer = CountingAllocator<T, 1>;
        using Inner = CountingAllocator<T, 2>;
        using SA = std::scoped_allocator_adaptor<Outer, Inner>;
        static_assert(!std::uses_allocator<T, Outer>::value, "");
        static_assert(std::uses_allocator<T, Inner>::value, "");
        T* ptr = (T*)::operator new(sizeof(T));
        Outer O(POuter);
        Inner I(PInner);
        SA A(O, I);
        int x = 42;
        int const& cx = x;
        A.construct(ptr, x, cx, std::move(x));
        assert((checkConstruct<int&, int const&, int&&>(*ptr, UA_AllocLast, I)));
        assert((POuter.checkConstruct<
                   int&, int const&, int&&,
                   SA::inner_allocator_type&>(O, ptr)));
        A.destroy(ptr);
        ::operator delete((void*)ptr);
    }
    PInner.reset();
    POuter.reset();
}

int main(int, char**) {
    test_bullet_one();
    test_bullet_two();
    test_bullet_three();

  return 0;
}
