xref: /llvm-project/clang/test/SemaTemplate/concepts-using-decl.cpp (revision 56099d242809f80984e4afa37693177484aab13d)
1*56099d24SUtkarsh Saxena // RUN: %clang_cc1 -std=c++20 -verify %s
2*56099d24SUtkarsh Saxena 
3*56099d24SUtkarsh Saxena namespace static_methods {
4*56099d24SUtkarsh Saxena template<class> concept False = false;
5*56099d24SUtkarsh Saxena 
6*56099d24SUtkarsh Saxena struct Base {
7*56099d24SUtkarsh Saxena     static void foo(auto);
8*56099d24SUtkarsh Saxena };
9*56099d24SUtkarsh Saxena struct Derived : public Base {
10*56099d24SUtkarsh Saxena     using Base::foo;
11*56099d24SUtkarsh Saxena     static void foo(False auto);
12*56099d24SUtkarsh Saxena };
func()13*56099d24SUtkarsh Saxena void func() {
14*56099d24SUtkarsh Saxena     Derived::foo(42);
15*56099d24SUtkarsh Saxena }
16*56099d24SUtkarsh Saxena } // namespace static_methods
17*56099d24SUtkarsh Saxena 
18*56099d24SUtkarsh Saxena namespace constrained_members {
19*56099d24SUtkarsh Saxena template <unsigned n> struct Opaque {};
expect(Opaque<n> _)20*56099d24SUtkarsh Saxena template <unsigned n> void expect(Opaque<n> _) {}
21*56099d24SUtkarsh Saxena 
22*56099d24SUtkarsh Saxena struct Empty{};
23*56099d24SUtkarsh Saxena constexpr int EmptySize = sizeof(Empty);
24*56099d24SUtkarsh Saxena 
25*56099d24SUtkarsh Saxena template<typename T> concept IsEmpty = sizeof(T) == EmptySize;
26*56099d24SUtkarsh Saxena 
27*56099d24SUtkarsh Saxena namespace base_members_not_hidden {
28*56099d24SUtkarsh Saxena struct base {
29*56099d24SUtkarsh Saxena   template <typename T>
fooconstrained_members::base_members_not_hidden::base30*56099d24SUtkarsh Saxena   Opaque<0> foo() { return Opaque<0>(); };
31*56099d24SUtkarsh Saxena };
32*56099d24SUtkarsh Saxena 
33*56099d24SUtkarsh Saxena struct bar1 : public base {
34*56099d24SUtkarsh Saxena   using base::foo;
35*56099d24SUtkarsh Saxena   template <typename T> requires IsEmpty<T>
fooconstrained_members::base_members_not_hidden::bar136*56099d24SUtkarsh Saxena   Opaque<1> foo() { return Opaque<1>(); };
37*56099d24SUtkarsh Saxena };
38*56099d24SUtkarsh Saxena 
39*56099d24SUtkarsh Saxena struct bar2 : public base {
40*56099d24SUtkarsh Saxena   using base::foo;
41*56099d24SUtkarsh Saxena   template <IsEmpty T>
fooconstrained_members::base_members_not_hidden::bar242*56099d24SUtkarsh Saxena   Opaque<1> foo() { return Opaque<1>(); };
43*56099d24SUtkarsh Saxena };
44*56099d24SUtkarsh Saxena 
45*56099d24SUtkarsh Saxena struct bar3 : public base {
46*56099d24SUtkarsh Saxena   using base::foo;
47*56099d24SUtkarsh Saxena   template <typename T>
fooconstrained_members::base_members_not_hidden::bar348*56099d24SUtkarsh Saxena   Opaque<1> foo() requires IsEmpty<T> { return Opaque<1>(); };
49*56099d24SUtkarsh Saxena };
50*56099d24SUtkarsh Saxena 
func()51*56099d24SUtkarsh Saxena void func() {
52*56099d24SUtkarsh Saxena   expect<0>(base{}.foo<Empty>());
53*56099d24SUtkarsh Saxena   expect<0>(base{}.foo<int>());
54*56099d24SUtkarsh Saxena   expect<1>(bar1{}.foo<Empty>());
55*56099d24SUtkarsh Saxena   expect<0>(bar1{}.foo<int>());
56*56099d24SUtkarsh Saxena   expect<1>(bar2{}.foo<Empty>());
57*56099d24SUtkarsh Saxena   expect<0>(bar2{}.foo<int>());
58*56099d24SUtkarsh Saxena   expect<1>(bar3{}.foo<Empty>());
59*56099d24SUtkarsh Saxena   expect<0>(bar3{}.foo<int>());
60*56099d24SUtkarsh Saxena }
61*56099d24SUtkarsh Saxena }
62*56099d24SUtkarsh Saxena namespace base_members_hidden {
63*56099d24SUtkarsh Saxena struct base1 {
64*56099d24SUtkarsh Saxena   template <typename T> requires IsEmpty<T>
fooconstrained_members::base_members_hidden::base165*56099d24SUtkarsh Saxena   Opaque<0> foo() { return Opaque<0>(); }; // expected-note {{candidate function}}
66*56099d24SUtkarsh Saxena };
67*56099d24SUtkarsh Saxena struct bar1 : public base1 {
68*56099d24SUtkarsh Saxena   using base1::foo;
69*56099d24SUtkarsh Saxena   template <typename T> requires IsEmpty<T>
fooconstrained_members::base_members_hidden::bar170*56099d24SUtkarsh Saxena   Opaque<1> foo() { return Opaque<1>(); };
71*56099d24SUtkarsh Saxena };
72*56099d24SUtkarsh Saxena struct base2 {
73*56099d24SUtkarsh Saxena   template <IsEmpty T>
fooconstrained_members::base_members_hidden::base274*56099d24SUtkarsh Saxena   Opaque<0> foo() { return Opaque<0>(); };
75*56099d24SUtkarsh Saxena };
76*56099d24SUtkarsh Saxena struct bar2 : public base2 {
77*56099d24SUtkarsh Saxena   using base2::foo;
78*56099d24SUtkarsh Saxena   template <IsEmpty T>
fooconstrained_members::base_members_hidden::bar279*56099d24SUtkarsh Saxena   Opaque<1> foo() { return Opaque<1>(); };
80*56099d24SUtkarsh Saxena };
81*56099d24SUtkarsh Saxena struct baz : public base1 {
82*56099d24SUtkarsh Saxena   using base1::foo;
83*56099d24SUtkarsh Saxena   template <typename T> requires IsEmpty<T> && IsEmpty<T>
fooconstrained_members::base_members_hidden::baz84*56099d24SUtkarsh Saxena   Opaque<1> foo() { return Opaque<1>(); };  // expected-note {{candidate function}}
85*56099d24SUtkarsh Saxena };
func()86*56099d24SUtkarsh Saxena void func() {
87*56099d24SUtkarsh Saxena   expect<0>(base1{}.foo<Empty>());
88*56099d24SUtkarsh Saxena   expect<1>(bar1{}.foo<Empty>());
89*56099d24SUtkarsh Saxena   expect<0>(base2{}.foo<Empty>());
90*56099d24SUtkarsh Saxena   expect<1>(bar2{}.foo<Empty>());
91*56099d24SUtkarsh Saxena   baz{}.foo<Empty>(); // expected-error {{call to member function 'foo' is ambiguous}}
92*56099d24SUtkarsh Saxena }
93*56099d24SUtkarsh Saxena } // namespace base_members_hidden
94*56099d24SUtkarsh Saxena 
95*56099d24SUtkarsh Saxena namespace same_contraint_at_different_place {
96*56099d24SUtkarsh Saxena struct base {
97*56099d24SUtkarsh Saxena   template <IsEmpty T>
foo1constrained_members::same_contraint_at_different_place::base98*56099d24SUtkarsh Saxena   void foo1() {}; // expected-note 2 {{candidate function}}
99*56099d24SUtkarsh Saxena   template <typename T> requires IsEmpty<T>
foo2constrained_members::same_contraint_at_different_place::base100*56099d24SUtkarsh Saxena   void foo2() {}; // expected-note 2 {{candidate function}}
101*56099d24SUtkarsh Saxena   template <typename T>
foo3constrained_members::same_contraint_at_different_place::base102*56099d24SUtkarsh Saxena   void foo3() requires IsEmpty<T> {}; // expected-note 2 {{candidate function}}
103*56099d24SUtkarsh Saxena };
104*56099d24SUtkarsh Saxena struct bar1 : public base {
105*56099d24SUtkarsh Saxena   using base::foo1;
106*56099d24SUtkarsh Saxena   using base::foo2;
107*56099d24SUtkarsh Saxena   using base::foo3;
108*56099d24SUtkarsh Saxena   template <typename T> requires IsEmpty<T>
foo1constrained_members::same_contraint_at_different_place::bar1109*56099d24SUtkarsh Saxena   void foo1() {}; // expected-note {{candidate function}}
110*56099d24SUtkarsh Saxena   template <IsEmpty T>
foo2constrained_members::same_contraint_at_different_place::bar1111*56099d24SUtkarsh Saxena   void foo2() {}; // expected-note {{candidate function}}
112*56099d24SUtkarsh Saxena   template <IsEmpty T>
foo3constrained_members::same_contraint_at_different_place::bar1113*56099d24SUtkarsh Saxena   void foo3() {}; // expected-note {{candidate function}}
114*56099d24SUtkarsh Saxena };
115*56099d24SUtkarsh Saxena struct bar2 : public base {
116*56099d24SUtkarsh Saxena   using base::foo1;
117*56099d24SUtkarsh Saxena   using base::foo2;
118*56099d24SUtkarsh Saxena   using base::foo3;
119*56099d24SUtkarsh Saxena   template <typename T>
foo1constrained_members::same_contraint_at_different_place::bar2120*56099d24SUtkarsh Saxena   void foo1() requires IsEmpty<T> {}; // expected-note {{candidate function}}
121*56099d24SUtkarsh Saxena   template <typename T>
foo2constrained_members::same_contraint_at_different_place::bar2122*56099d24SUtkarsh Saxena   void foo2() requires IsEmpty<T> {}; // expected-note {{candidate function}}
123*56099d24SUtkarsh Saxena   template <typename T> requires IsEmpty<T>
foo3constrained_members::same_contraint_at_different_place::bar2124*56099d24SUtkarsh Saxena   void foo3() {}; // expected-note {{candidate function}}
125*56099d24SUtkarsh Saxena };
func()126*56099d24SUtkarsh Saxena void func() {
127*56099d24SUtkarsh Saxena   bar1{}.foo1<Empty>(); // expected-error {{call to member function 'foo1' is ambiguous}}
128*56099d24SUtkarsh Saxena   bar1{}.foo2<Empty>(); // expected-error {{call to member function 'foo2' is ambiguous}}
129*56099d24SUtkarsh Saxena   bar1{}.foo3<Empty>(); // expected-error {{call to member function 'foo3' is ambiguous}}
130*56099d24SUtkarsh Saxena   bar2{}.foo1<Empty>(); // expected-error {{call to member function 'foo1' is ambiguous}}
131*56099d24SUtkarsh Saxena   bar2{}.foo2<Empty>(); // expected-error {{call to member function 'foo2' is ambiguous}}
132*56099d24SUtkarsh Saxena   bar2{}.foo3<Empty>(); // expected-error {{call to member function 'foo3' is ambiguous}}
133*56099d24SUtkarsh Saxena }
134*56099d24SUtkarsh Saxena } // namespace same_constraint_at_different_place
135*56099d24SUtkarsh Saxena 
136*56099d24SUtkarsh Saxena namespace more_constrained {
137*56099d24SUtkarsh Saxena struct base1 {
fooconstrained_members::more_constrained::base1138*56099d24SUtkarsh Saxena   template <class T> Opaque<0> foo() { return Opaque<0>(); }
139*56099d24SUtkarsh Saxena };
140*56099d24SUtkarsh Saxena struct derived1 : base1 {
141*56099d24SUtkarsh Saxena   using base1::foo;
fooconstrained_members::more_constrained::derived1142*56099d24SUtkarsh Saxena   template <IsEmpty T> Opaque<1> foo() { return Opaque<1>(); }
143*56099d24SUtkarsh Saxena };
144*56099d24SUtkarsh Saxena struct base2 {
fooconstrained_members::more_constrained::base2145*56099d24SUtkarsh Saxena   template <IsEmpty T> Opaque<0> foo() { return Opaque<0>(); }
146*56099d24SUtkarsh Saxena };
147*56099d24SUtkarsh Saxena struct derived2 : base2 {
148*56099d24SUtkarsh Saxena   using base2::foo;
fooconstrained_members::more_constrained::derived2149*56099d24SUtkarsh Saxena   template <class T> Opaque<1> foo() { return Opaque<1>(); }
150*56099d24SUtkarsh Saxena };
func()151*56099d24SUtkarsh Saxena void func() {
152*56099d24SUtkarsh Saxena   expect<0>(derived1{}.foo<int>());
153*56099d24SUtkarsh Saxena   expect<1>(derived1{}.foo<Empty>());
154*56099d24SUtkarsh Saxena   expect<0>(derived2{}.foo<Empty>());
155*56099d24SUtkarsh Saxena   expect<1>(derived2{}.foo<int>());
156*56099d24SUtkarsh Saxena }
157*56099d24SUtkarsh Saxena } // namespace more_constrained
158*56099d24SUtkarsh Saxena } // namespace constrained_members
159*56099d24SUtkarsh Saxena 
160*56099d24SUtkarsh Saxena namespace heads_without_concepts {
161*56099d24SUtkarsh Saxena struct base {
162*56099d24SUtkarsh Saxena   template <int N, int M>
fooheads_without_concepts::base163*56099d24SUtkarsh Saxena   int foo() { return 1; };
164*56099d24SUtkarsh Saxena };
165*56099d24SUtkarsh Saxena 
166*56099d24SUtkarsh Saxena struct bar : public base {
167*56099d24SUtkarsh Saxena   using base::foo;
168*56099d24SUtkarsh Saxena   template <int N>
fooheads_without_concepts::bar169*56099d24SUtkarsh Saxena   int foo() { return 2; }; // expected-note {{candidate template ignored: substitution failure: too many template arguments for function template 'foo'}}
170*56099d24SUtkarsh Saxena };
171*56099d24SUtkarsh Saxena 
func()172*56099d24SUtkarsh Saxena void func() {
173*56099d24SUtkarsh Saxena   bar f;
174*56099d24SUtkarsh Saxena   f.foo<10>();
175*56099d24SUtkarsh Saxena   // FIXME(GH58571): bar::foo should not hide base::foo.
176*56099d24SUtkarsh Saxena   f.foo<10, 10>(); // expected-error {{no matching member function for call to 'foo'}}
177*56099d24SUtkarsh Saxena }
178*56099d24SUtkarsh Saxena } // namespace heads_without_concepts.
179