Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CXX / temp / temp.decls / temp.fct / temp.func.order / p6.cpp
blob9f44878da625429c4364fc36e827d678c9efc826
1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
3 template <typename> constexpr bool True = true;
4 template <typename T> concept C = True<T>;
5 template <typename T> concept D = C<T> && sizeof(T) > 2;
6 template <typename T> concept E = D<T> && alignof(T) > 1;
8 struct A {};
9 template <typename, auto, int, A, typename...> struct S {};
10 template <typename, auto, int, A, auto...> struct S2 {};
11 template <typename T, typename U> struct X {};
13 namespace p6 {
15 struct B;
17 void f(C auto &, auto &) = delete;
18 template <C Q> void f(Q &, C auto &);
20 void g(struct A *ap, struct B *bp) {
21 f(*ap, *bp);
24 #if 0
25 // FIXME: [temp.func.order]p6.2.1 is not implemented, matching GCC.
26 template <typename T, C U, typename V> bool operator==(X<T, U>, V) = delete;
27 template <C T, C U, C V> bool operator==(T, X<U, V>);
29 bool h() {
30 return X<void *, int>{} == 0;
32 #endif
34 template<C T, C auto M, int W, A S,
35 template<typename, auto, int, A, typename...> class U,
36 typename... Z>
37 void foo(T, U<T, M, W, S, Z...>) = delete;
38 template<C T, D auto M, int W, A S,
39 template<typename, auto, int, A, typename...> class U,
40 typename... Z>
41 void foo(T, U<T, M, W, S, Z...>) = delete;
42 template<C T, E auto M, int W, A S,
43 template<typename, auto, int, A, typename...> class U,
44 typename... Z>
45 void foo(T, U<T, M, W, S, Z...>);
47 void bar(S<int, 1, 1, A{}, int> s, S2<int, 1, 1, A{}, 0, 0u> s2) {
48 foo(0, s);
51 template<C auto... T> void bar2();
52 template<D auto... T> void bar2() = delete;
54 } // namespace p6
56 namespace TestConversionFunction {
57 struct Y {
58 template<C T, typename U> operator X<T, U>(); // expected-note {{candidate function [with T = int, U = int]}}
59 template<typename T, typename U> operator X<U, T>(); // expected-note {{candidate function [with T = int, U = int]}}
62 X<int,int> f() {
63 return Y{}; // expected-error {{conversion from 'Y' to 'X<int, int>' is ambiguous}}
67 namespace ClassPartialSpecPartialOrdering {
68 template<D T> struct Y { Y()=delete; }; // expected-note {{template is declared here}}
69 template<C T> struct Y<T> {}; // expected-error {{class template partial specialization is not more specialized than the primary template}}
71 template<C T, int I> struct Y1 { Y1()=delete; };
72 template<D T> struct Y1<T, 2> { Y1()=delete; };
73 template<E T> struct Y1<T, 1+1> {};
75 template<class T, int I, int U> struct Y2 {};
76 template<class T, int I> struct Y2<T*, I, I+2> {}; // expected-note {{partial specialization matches}}
77 template<C T, int I> struct Y2<T*, I, I+1+1> {}; // expected-note {{partial specialization matches}}
79 template<C T, C auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>
80 struct Y3 { Y3()=delete; };
81 template<C T, D auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>
82 struct Y3<T, I, W, S, U, Z...> { Y3()=delete; };
83 template<C T, E auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>
84 struct Y3<T, I, W, S, U, Z...> {};
86 void f() {
87 Y1<int, 2> a;
88 Y2<char*, 1, 3> b; // expected-error {{ambiguous partial specializations}}
89 Y3<int, 1, 1, A{}, S, int> c;
92 // Per [temp.func.order]p6.2.2, specifically "if the function parameters that
93 // positionally correspond between the two templates are not of the same type",
94 // this partial specialization does not work.
95 // See https://github.com/llvm/llvm-project/issues/58896
96 template<C T, C V> struct Y4; // expected-note {{template is declared here}}
97 template<D T, C V> struct Y4<V, T>; // expected-error {{class template partial specialization is not more specialized than the primary template}}
99 template<C auto T> struct W1;
100 template<D auto T> struct W1<T> {};
102 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
103 // template<C auto... T> struct W2;
104 // template<D auto... T> struct W2<T...> {};
106 template<class T, class U>
107 concept C1 = C<T> && C<U>;
108 template<class T, class U>
109 concept D1 = D<T> && C<U>;
111 template<C1<A> auto T> struct W3;
112 template<D1<A> auto T> struct W3<T> {};
114 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
115 // template<C1<A> auto... T> struct W4;
116 // template<D1<A> auto... T> struct W4<T...> {};
118 // FIXME: enable once Clang support non-trivial auto on NTTP.
119 // template<C auto* T> struct W5;
120 // template<D auto* T> struct W5<T> {};
122 // FIXME: enable once Clang support non-trivial auto on NTTP.
123 // template<C auto& T> struct W6;
124 // template<D auto& T> struct W6<T> {};
126 struct W1<0> w1;
127 // struct W2<0> w2;
128 struct W3<0> w3;
129 // struct W4<0> w4;
130 // FIXME: enable once Clang support non-trivial auto on NTTP.
131 // struct W5<(int*)nullptr> w5;
132 // struct W6<w5> w6;
135 namespace PR53640 {
137 template <typename T>
138 concept C = true;
140 template <C T>
141 void f(T t) {} // expected-note {{candidate function [with T = int]}}
143 template <typename T>
144 void f(const T &t) {} // expected-note {{candidate function [with T = int]}}
146 int g() {
147 f(0); // expected-error {{call to 'f' is ambiguous}}
150 struct S {
151 template <typename T> explicit S(T) noexcept requires C<T> {} // expected-note {{candidate constructor}}
152 template <typename T> explicit S(const T &) noexcept {} // expected-note {{candidate constructor}}
155 int h() {
156 S s(4); // expected-error-re {{call to constructor of {{.*}} is ambiguous}}
161 namespace NestedConstraintsDiffer {
162 template<typename T> concept A = true;
163 template<typename T> concept B = A<T> && true;
165 // This is valid: we can compare the constraints of the two overloads of `f`
166 // because the template-parameters are equivalent, despite having different
167 // constraints.
168 template<typename T> struct Z {};
169 template<template<typename T> typename> struct X {};
170 template<A U, template<A T> typename TT> void f(U, X<TT>) {}
171 template<B U, template<B T> typename TT> void f(U, X<TT>) {}
172 void g(X<Z> x) { f(0, x); }
174 // Same thing with a constrained non-type parameter.
175 template<auto N> struct W {};
176 template<template<auto> typename> struct Y {};
177 template<A U, template<A auto> typename TT> void h(U, Y<TT>) {}
178 template<B U, template<B auto> typename TT> void h(U, Y<TT>) {}
179 void i(Y<W> x) { h(0, x); }