113 lines
2.6 KiB
C++

// RUN: %clang_cc1 -fsyntax-only -verify -std=c++26 %s
namespace t1 {
template<int N> struct A {
template<class C> friend auto cica(const A<N-1>&, C) {
return N;
}
};
template<> struct A<0> {
template<class C> friend auto cica(const A<0>&, C);
// expected-note@-1 {{declared here}}
};
void test() {
cica(A<0>{}, 0);
// expected-error@-1 {{function 'cica<int>' with deduced return type cannot be used before it is defined}}
(void)A<1>{};
cica(A<0>{}, 0);
}
} // namespace t1
namespace t2 {
template<int N> struct A {
template<class C> friend auto cica(const A<N-1>&, C) {
return N;
}
};
template<> struct A<0> {
template<class C> friend auto cica(const A<0>&, C);
};
template <int N, class = decltype(cica(A<N>{}, nullptr))>
void MakeCica();
// expected-note@-1 {{candidate function}}
template <int N> void MakeCica(A<N+1> = {});
// expected-note@-1 {{candidate function}}
void test() {
MakeCica<0>();
MakeCica<0>();
// expected-error@-1 {{call to 'MakeCica' is ambiguous}}
}
} // namespace t2
namespace t3 {
template<int N> struct A {
template<class C> friend auto cica(const A<N-1>&, C) {
return N-1;
}
};
template<> struct A<0> {
template<class C> friend auto cica(const A<0>&, C);
};
template <int N, class AT, class = decltype(cica(AT{}, nullptr))>
static constexpr bool MakeCica(int);
template <int N, class AT>
static constexpr bool MakeCica(short, A<N+1> = {});
template <int N, class AT = A<N>, class Val = decltype(MakeCica<N, AT>(0))>
static constexpr bool has_cica = Val{};
constexpr bool cica2 = has_cica<0> || has_cica<0>;
} // namespace t3
namespace t4 {
template<int N> struct A {
template<class C> friend auto cica(const A<N-1>&, C);
};
template<> struct A<0> {
template<class C> friend auto cica(const A<0>&, C) {
C a;
}
};
template struct A<1>;
void test() {
cica(A<0>{}, 0);
}
} // namespace t4
namespace regression1 {
template <class> class A;
template <class T> [[gnu::abi_tag("TAG")]] void foo(A<T>);
template <class> struct A {
friend void foo <>(A);
};
template struct A<int>;
template <class T> [[gnu::abi_tag("TAG")]] void foo(A<T>) {}
template void foo<int>(A<int>);
} // namespace regression1
namespace regression2 {
template <class> struct A {
template <class T> static void f() {
A<int>::f<T>();
}
};
template <> template <class T> void A<int>::f() {
static_assert(__is_same(T, long));
}
template void A<void>::f<long>();
} // namespace regression2