//===----------------------------------------------------------------------===//
//
// 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
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14

// <memory>

// template <ObjectType T> constexpr T* addressof(T& r);

#include <cuda/std/type_traits>
#include <cuda/std/cassert>

#include "test_macros.h"

#if defined(_LIBCUDACXX_ADDRESSOF) || defined(__NVCOMPILER)
struct Pointer {
  __host__ __device__ constexpr Pointer(void* v) : value(v) {}
  void* value;
};

struct A
{
    __host__ __device__ constexpr A() : n(42) {}
    __host__ __device__ void operator&() const { }
    int n;
};

constexpr int global_integer = 0;
static_assert(cuda::std::addressof(global_integer) == &global_integer, "");

constexpr double global_double = 0.0;
static_assert(cuda::std::addressof(global_double) == &global_double, "");

#ifndef __CUDA_ARCH__ // fails in __cudaRegisterVariable
constexpr A global_struct{};
constexpr const A* address = cuda::std::addressof(global_struct);
static_assert(&(address->n) == &(global_struct.n), "");
#endif
#endif

int main(int, char**)
{
  return 0;
}
