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