181 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s2 3template <typename> constexpr bool True = true;4template <typename T> concept C = True<T>;5template <typename T> concept D = C<T> && sizeof(T) > 2;6template <typename T> concept E = D<T> && alignof(T) > 1;7 8struct A {};9template <typename, auto, int, A, typename...> struct S {};10template <typename, auto, int, A, auto...> struct S2 {};11template <typename T, typename U> struct X {};12 13namespace p6 {14 15struct B;16 17void f(C auto &, auto &) = delete;18template <C Q> void f(Q &, C auto &);19 20void g(struct A *ap, struct B *bp) {21 f(*ap, *bp);22}23 24#if 025// FIXME: [temp.func.order]p6.2.1 is not implemented, matching GCC.26template <typename T, C U, typename V> bool operator==(X<T, U>, V) = delete;27template <C T, C U, C V> bool operator==(T, X<U, V>);28 29bool h() {30 return X<void *, int>{} == 0;31}32#endif33 34template<C T, C auto M, int W, A S,35 template<typename, auto, int, A, typename...> class U,36 typename... Z>37void foo(T, U<T, M, W, S, Z...>) = delete;38template<C T, D auto M, int W, A S,39 template<typename, auto, int, A, typename...> class U,40 typename... Z>41void foo(T, U<T, M, W, S, Z...>) = delete;42template<C T, E auto M, int W, A S,43 template<typename, auto, int, A, typename...> class U,44 typename... Z>45void foo(T, U<T, M, W, S, Z...>);46 47void bar(S<int, 1, 1, A{}, int> s, S2<int, 1, 1, A{}, 0, 0u> s2) {48 foo(0, s);49}50 51template<C auto... T> void bar2();52template<D auto... T> void bar2() = delete;53 54} // namespace p655 56namespace TestConversionFunction {57struct 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]}}60};61 62X<int,int> f() {63 return Y{}; // expected-error {{conversion from 'Y' to 'X<int, int>' is ambiguous}}64}65}66 67namespace ClassPartialSpecPartialOrdering {68template<D T> struct Y { Y()=delete; }; // expected-note {{template is declared here}}69template<C T> struct Y<T> {}; // expected-error {{class template partial specialization is not more specialized than the primary template}}70 71template<C T, int I> struct Y1 { Y1()=delete; };72template<D T> struct Y1<T, 2> { Y1()=delete; };73template<E T> struct Y1<T, 1+1> {};74 75template<class T, int I, int U> struct Y2 {};76template<class T, int I> struct Y2<T*, I, I+2> {}; // expected-note {{partial specialization matches}}77template<C T, int I> struct Y2<T*, I, I+1+1> {}; // expected-note {{partial specialization matches}}78 79template<C T, C auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>80struct Y3 { Y3()=delete; };81template<C T, D auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>82struct Y3<T, I, W, S, U, Z...> { Y3()=delete; };83template<C T, E auto I, int W, A S, template<typename, auto, int, A, typename...> class U, typename... Z>84struct Y3<T, I, W, S, U, Z...> {};85 86void 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;90}91 92// Per [temp.func.order]p6.2.2, specifically "if the function parameters that93// 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/5889696template<C T, C V> struct Y4; // expected-note {{template is declared here}}97template<D T, C V> struct Y4<V, T>; // expected-error {{class template partial specialization is not more specialized than the primary template}}98 99template<C auto T> struct W1;100template<D auto T> struct W1<T> {};101 102// See http://cplusplus.github.io/concepts-ts/ts-active.html#28103// template<C auto... T> struct W2;104// template<D auto... T> struct W2<T...> {};105 106template<class T, class U>107concept C1 = C<T> && C<U>;108template<class T, class U>109concept D1 = D<T> && C<U>;110 111template<C1<A> auto T> struct W3;112template<D1<A> auto T> struct W3<T> {};113 114// See http://cplusplus.github.io/concepts-ts/ts-active.html#28115// template<C1<A> auto... T> struct W4;116// template<D1<A> auto... T> struct W4<T...> {};117 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> {};121 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> {};125 126struct W1<0> w1;127// struct W2<0> w2;128struct 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;133}134 135namespace PR53640 {136 137template <typename T>138concept C = true;139 140template <C T>141void f(T t) {} // expected-note {{candidate function [with T = int]}}142 143template <typename T>144void f(const T &t) {} // expected-note {{candidate function [with T = int]}}145 146int g() {147 f(0); // expected-error {{call to 'f' is ambiguous}}148}149 150struct 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}}153};154 155int h() {156 S s(4); // expected-error-re {{call to constructor of {{.*}} is ambiguous}}157}158 159}160 161namespace NestedConstraintsDiffer {162 template<typename T> concept A = true;163 template<typename T> concept B = A<T> && true;164 165 // This is valid: we can compare the constraints of the two overloads of `f`166 // because the template-parameters are equivalent, despite having different167 // 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); }173 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); }180}181