llvm/clang/test/SemaTemplate/temp_arg_nontype_cxx2c.cpp

// RUN: %clang_cc1 -fsyntax-only -std=c++2c -Wconversion -verify %s

struct Test {
    int a = 0;
    int b = 42;
};

template <Test t>
struct A {
    static constexpr auto a = t.a;
    static constexpr auto b = t.b;
};

template <auto N>
struct Auto {};

template <typename T, T elem>
struct Explicit{};

struct L {};
struct M {};

struct Constructor {
    Constructor(L) {}; // expected-note {{here}}
    constexpr Constructor(M){};
};

template < Test = {} >
struct DefaultParam1{};

template < Test = {1, 2} >
struct DefaultParam2{};

template < Test = {. b = 5} >
struct DefaultParam3{};

void test() {
    static_assert(A<{}>::a == 0);
    static_assert(A<{}>::b == 42);
    static_assert(A<{.a = 3}>::a == 3);
    static_assert(A<{.b = 4}>::b == 4);

    Auto<{0}> a; // expected-error {{cannot deduce type of initializer list}}

    int notconst = 0; // expected-note {{declared here}}
    A<{notconst}> _; // expected-error {{non-type template argument is not a constant expression}} \
                     // expected-note  {{read of non-const variable 'notconst' is not allowed in a constant expression}}


    Explicit<Constructor, {L{}}> err; // expected-error {{non-type template argument is not a constant expression}} \
                                      // expected-note {{non-constexpr constructor 'Constructor' cannot be used in a constant expression}}
    Explicit<Constructor, {M{}}> ok;


    DefaultParam1<> d1;
    DefaultParam2<> d2;
    DefaultParam3<> d3;
}

template<auto n> struct B { /* ... */ };
template<int i> struct C { /* ... */ };
C<{ 42 }> c1;  // expected-warning {{braces around scalar initializer}}

struct J1 {
  J1 *self=this;
};
B<J1{}> j1;  // expected-error {{pointer to temporary object is not allowed in a template argument}}

struct J2 {
  J2 *self=this;
  constexpr J2() {}
  constexpr J2(const J2&) {}
};
B<J2{}> j2;  // expected-error {{pointer to temporary object is not allowed in a template argument}}


namespace GH58434 {

template<int>
void f();

void test() {
  f<{42}>();
}

}

namespace GH73666 {

template<class T, int I>
struct A {
    T x[I];
};

template< class T, class... U >
A( T, U... ) -> A<T, 1 + sizeof...(U)>;

template<A a> void foo() { }

void bar() {
    foo<{1}>();
}

}

namespace GH84052 {

template <class... T>
concept C = sizeof(T...[1]) == 1; // #C

struct A {};

template <class T, C<T> auto = A{}> struct Set {}; // #Set

template <class T> void foo() {
  Set<T> unrelated;
}

Set<bool> sb;
Set<float> sf;
// expected-error@-1 {{constraints not satisfied for class template 'Set'}}
// expected-note@#Set {{because 'C<decltype(GH84052::A{}), float>' evaluated to false}}
// expected-note@#C {{evaluated to false}}

} // namespace GH84052