// 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
// RUN: cxx_compiler cxx_11 -c %s -o %t.o
// RUN: bindump %t.o | FileCheck prefixes %s

#include <cstddef>
// CHECK-DAG: _Z3f24Dn
void f24(std::nullptr_t) {}

// decltype
// CHECK-DAG: _Z3f25ILi3EEvDtT_E
template <int I> void f25(decltype(I));
template<> void f25<3>(int) {}

// CHECK-DAG: _Z1FIiEDTcl1gfp_EET_
void g(int);
template <class T> auto F(T p)->decltype(g(p));
// return type in the mangling of the template signature is encoded as DTcl1gfp_E
template <> auto F(int p)->decltype(g(p)) {}

// CHECK-DAG: _Z1fN1SUt_E
struct S { static struct {} x; };
typedef decltype(S::x) TX;
void f(TX) {}

// CHECK-DAG: _ZN1S1xE
TX S::x;

// Function parameter references
// CHECK-DAG: _Z1fIiEvT_DtfL0p_E
template <class T> void f(T p, decltype(p));
template <> void f(int p, decltype(p)) {}

// CHECK-DAG: _Z1gIiEvT_PFDtfL0p_EvE
template <class T> void g(T p, decltype(p) (*)());
template <> void g(int p, decltype(p) (*)()) {}

// CHECK-DAG: _Z1hIiEvT_PFDtfL0p_EvE
template <class T> void h(T p, auto (*)()->decltype(p));
template <> void h(int p, auto (*)()->decltype(p)) {}

// CHECK-DAG: _Z1iIiEvT_PFDtfp_ES0_E
template <class T> void i(T p, auto (*)(T q)->decltype(q));
template <> void i(int p, auto (*)(int q)->decltype(q)) {}

// CHECK-DAG: _Z1jIiEvT_PFS0_DtfL1p_EE
template <class T> void j(T p, auto (*)(decltype(p))->T);
template <> void j(int p, auto (*)(decltype(p))->int) {}

// CHECK-DAG: _Z1kIiEvT_PFPAszfL0p__iS0_E
template <class T> void k(T p, int (*(*)(T p))[sizeof(p)]);
template <> void k(int p, int (*(*)(int p))[sizeof(p)]) {}

// CHECK-DAG: _Z1lIiEvT_PDtfL0pK_E
template<typename T> void l(T const p, decltype(p)*);
template <> void l(int p, int const *) {}

// Multiple function parameter references
// CHECK-DAG: _Z1mIiEvT_DtfL0p_ES0_DtfL0p1_E
template <class T> void m(T p, decltype(p), T q, decltype(q));
template <> void m(int p, decltype(p), int q, decltype(q)) {}

// CHECK-DAG: _Z1nIiEvT_PFDtfp0_ES0_S0_E
template <class T> void n(T p, auto (*)(T q, T r)->decltype(r));
template <> void n(int p, auto (*)(int q, int r)->decltype(r)) {}

// CHECK-DAG: _Z1oIiEvfT_PFDtfp0_EcS0_EPFDtfL0p0_ES0_E
template <class T> void o(float f, T p, auto (*)(char c, T q)->decltype(q), auto (*)(T q)->decltype(p));
template <> void o(float f, int p, auto (*)(char c, int q)->decltype(q), auto (*)(int q)->decltype(p)) {}


// CHECK-DAG: _Z3fffIP2S2EDtptfp_1xET_
struct S2 { long double x; };
template<class T> auto fff(T p)->decltype(p->x);
template <> auto fff(S2 *p)->decltype(p->x) { return 0; }

// CHECK-DAG: _Z3gggIN1N1XEEDtsrNT_1XE1yES2_
namespace N {
    struct X {
        long y;
    };
}
template<class T> auto ggg(T p)->decltype(T::X::y);
template<> auto ggg(N::X p)->decltype(N::X::y) { return 0; }

// CHECK-DAG: _ZN1A1fIPNS_1DEEEDtptfp_gssr1A1BE1xET_
namespace A {
    struct B { int x; };
    struct D : public B {};
    template<class T> auto f(T p)->decltype(p->::A::B::x);
    template <> auto f<D*>(D* p)->decltype(p->::A::B::x) { return 0; }
}

// CHECK-DAG: _Z3hhhI1QEDTpldtfp_1xdtL_Z1qE1xET_
struct Q {int x; } q;
template<class T> auto hhh(T p)->decltype(p.x + q.x);
template <> auto hhh(Q p)->decltype(p.x + q.x) { return 0; }

// CHECK-DAG: _Z3jjjIiEDTplfp_dtL_Z1dEsr1B1XIT_EE1xES0_
template<class T> struct X { static T x; };
struct B: X<int> {};
struct D: B {} d;
template<class T> auto jjj(T p)->decltype(p+d.B::X<T>::x);
template<> auto jjj(int p)->decltype(p+d.B::X<int>::x) { return 0; }

// new auto
// CHECK-DAG: _Z2kkIN1N1XEEvDTnw_DapicvT__EEE
template <typename T> void kk(decltype(new auto(T())) p) {}
template <> void kk<N::X>(N::X*) {}

// CHECK-DAG: _Z4foouDs
void foou(char16_t) {}

// CHECK-DAG: _Z4foouDi
void foou(char32_t) {}

namespace C {
    struct XX {
        struct Y {
        };
    };
    struct Z {
        XX x;
    };
    // CHECK-DAG: _ZN1C1fIPNS_1ZEEENDtptfp_1xE1YET_
    template<class T> auto f(T p)->typename decltype(p->x)::Y;
    template <> auto f<Z*>(Z* p)->decltype(p->x)::Y {}
    // CHECK-DAG: _ZN1C1fIPNS_1ZEEEvT_NDtptfL0p_1xE1YE
    template<class T> void f(T p, typename decltype(p->x)::Y);
    template <> void f<Z*>(Z* p, decltype(p->x)::Y) {}
};

// CHECK-DAG: _Zli8_literaly
unsigned long long operator"" _literal(unsigned long long i) { return i; }

// compiles on clang but not on g++
// is an example in the ABI document.
// ref-qualifier from n2439
// CHECK-DAG: _Z1fM2A2KFvvRE
struct A2 {};
void f(void (A2::*)() const &) {}

// CHECK-DAG: _Z1fM2A2KFvvOE
void f(void (A2::*)() const &&) {}
