xref: /llvm-project/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp (revision fd87d765c0455265aea4595a3741a96b4c078fbc)
1 // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++20 -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s
3 
4 
5 template <class T>
6 class A {
7 public:
f(T a)8    void f(T a) { }// expected-note 2{{must qualify identifier to find this declaration in dependent base class}}
9    void g();// expected-note 2{{must qualify identifier to find this declaration in dependent base class}}
10 };
11 
12 template <class T>
13 class B : public A<T> {
14 public:
z(T a)15 	void z(T a)
16     {
17        f(a); // expected-warning 2{{use of member 'f' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
18        g(); // expected-warning 2{{use of member 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
19     }
20 };
21 
22 template class B<int>; // expected-note {{requested here}}
23 template class B<char>; // expected-note {{requested here}}
24 
test()25 void test()
26 {
27     B<int> b;
28     b.z(3);
29 }
30 
31 struct A2 {
fA232   template<class T> void f(T) {
33     XX; //expected-error {{use of undeclared identifier 'XX'}}
34     A2::XX; //expected-error {{no member named 'XX' in 'A2'}}
35   }
36 };
37 template void A2::f(int);
38 
39 template<class T0>
40 struct A3 {
fA341   template<class T1> void f(T1) {
42     XX; //expected-error {{use of undeclared identifier 'XX'}}
43   }
44 };
45 template void A3<int>::f(int);
46 
47 template<class T0>
48 struct A4 {
fA449   void f(char) {
50     XX; //expected-error {{use of undeclared identifier 'XX'}}
51   }
52 };
53 template class A4<int>;
54 
55 
56 namespace lookup_dependent_bases_id_expr {
57 
58 template<class T> class A {
59 public:
60   int var;
61 };
62 
63 
64 template<class T>
65 class B : public A<T> {
66 public:
f()67   void f() {
68     var = 3; // expected-warning {{use of undeclared identifier 'var'; unqualified lookup into dependent bases of class template 'B' is a Microsoft extension}}
69   }
70 };
71 
72 template class B<int>;
73 
74 template<typename T> struct C;
75 
76 // Test lookup with incomplete lookup context
77 template<typename T>
f()78 auto C<T>::f() -> decltype(x) { } // expected-error {{use of undeclared identifier 'x'}}
79                                   // expected-error@-1 {{out-of-line definition of 'f' from class 'C<T>' without definition}}
80 
81 }
82 
83 
84 
85 namespace lookup_dependent_base_class_static_function {
86 
87 template <class T>
88 class A {
89 public:
90    static void static_func();// expected-note {{must qualify identifier to find this declaration in dependent base class}}
91    void func();// expected-note {{must qualify identifier to find this declaration in dependent base class}}
92 };
93 
94 
95 template <class T>
96 class B : public A<T> {
97 public:
z2()98   static void z2(){
99     static_func();  // expected-warning {{use of member 'static_func' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
100     func(); // expected-warning {{use of member 'func' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-error {{call to non-static member function without an object argument}}
101   }
102 };
103 template class B<int>; // expected-note {{requested here}}
104 
105 }
106 
107 
108 
109 namespace lookup_dependent_base_class_default_argument {
110 
111 template<class T>
112 class A {
113 public:
114   static int f1(); // expected-note {{must qualify identifier to find this declaration in dependent base class}}
115   int f2(); // expected-note {{must qualify identifier to find this declaration in dependent base class}}
116 };
117 
118 template<class T>
119 class B : public A<T> {
120 public:
121   void g1(int p = f1());// expected-warning {{use of member 'f1' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
122   void g2(int p = f2());// expected-warning {{use of member 'f2' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-error {{call to non-static member function without an object argument}}
123 };
124 
foo()125 void foo()
126 {
127 	B<int> b;
128 	b.g1(); // expected-note {{required here}}
129 	b.g2(); // expected-note {{required here}}
130 }
131 
132 }
133 
134 
135 namespace lookup_dependent_base_class_friend {
136 
137 template <class T>
138 class B {
139 public:
140   static void g();  // expected-note {{must qualify identifier to find this declaration in dependent base class}}
141 };
142 
143 template <class T>
144 class A : public B<T> {
145 public:
foo(A<T> p)146   friend void foo(A<T> p){
147     g(); // expected-warning {{use of member 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
148   }
149 };
150 
main2()151 int main2()
152 {
153   A<int> a;
154   foo(a); // expected-note {{requested here}}
155 }
156 
157 }
158 
159 
160 namespace lookup_dependent_base_no_typo_correction {
161 
162 class C {
163 public:
164   int m_hWnd;
165 };
166 
167 template <class T>
168 class A : public T {
169 public:
f(int hWnd)170   void f(int hWnd) {
171     m_hWnd = 1; // expected-warning {{use of undeclared identifier 'm_hWnd'; unqualified lookup into dependent bases of class template 'A' is a Microsoft extension}}
172   }
173 };
174 
175 template class A<C>;
176 
177 }
178 
179 namespace PR12701 {
180 
181 class A {};
182 class B {};
183 
184 template <class T>
185 class Base {
186  public:
base_fun(void * p)187   bool base_fun(void* p) { return false; }  // expected-note {{must qualify identifier to find this declaration in dependent base class}}
operator T*() const188   operator T*() const { return 0; }
189 };
190 
191 template <class T>
192 class Container : public Base<T> {
193  public:
194   template <typename S>
operator =(const Container<S> & rhs)195   bool operator=(const Container<S>& rhs) {
196     return base_fun(rhs);  // expected-warning {{use of member 'base_fun' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
197   }
198 };
199 
f()200 void f() {
201   Container<A> text_provider;
202   Container<B> text_provider2;
203   text_provider2 = text_provider;  // expected-note {{in instantiation of function template specialization}}
204 }
205 
206 }  // namespace PR12701
207 
208 namespace PR16014 {
209 
210 struct A {
211   int a;
212   static int sa;
213 };
214 template <typename T> struct B : T {
fooPR16014::B215   int     foo() { return a; }           // expected-warning {{lookup into dependent bases}}
barPR16014::B216   int    *bar() { return &a; }          // expected-warning {{lookup into dependent bases}}
bazPR16014::B217   int     baz() { return T::a; }
quxPR16014::B218   int T::*qux() { return &T::a; }
stuffPR16014::B219   static int T::*stuff() { return &T::a; }
stuff1PR16014::B220   static int stuff1() { return T::sa; }
stuff2PR16014::B221   static int *stuff2() { return &T::sa; }
stuff3PR16014::B222   static int stuff3() { return sa; }    // expected-warning {{lookup into dependent bases}}
stuff4PR16014::B223   static int *stuff4() { return &sa; }  // expected-warning {{lookup into dependent bases}}
224 };
225 
226 template <typename T> struct C : T {
fooPR16014::C227   int     foo() { return b; }      // expected-error {{no member named 'b' in 'PR16014::C<A>'}} expected-warning {{lookup into dependent bases}}
barPR16014::C228   int    *bar() { return &b; }     // expected-error {{no member named 'b' in 'PR16014::C<A>'}} expected-warning {{lookup into dependent bases}}
bazPR16014::C229   int     baz() { return T::b; }   // expected-error {{no member named 'b' in 'PR16014::A'}}
quxPR16014::C230   int T::*qux() { return &T::b; }  // expected-error {{no member named 'b' in 'PR16014::A'}}
fuzPR16014::C231   int T::*fuz() { return &U::a; }  // expected-error {{no member named 'U' in 'PR16014::C<A>'}} \
232   // expected-warning {{unqualified lookup into dependent bases of class template 'C'}}
233 };
234 
235 template struct B<A>;
236 template struct C<A>;  // expected-note-re 1+ {{in instantiation of member function 'PR16014::C<PR16014::A>::{{.*}}' requested here}}
237 
238 template <typename T> struct D : T {
239   struct Inner {
fooPR16014::D::Inner240     int foo() {
241       // FIXME: MSVC can find this in D's base T!  Even worse, if ::sa exists,
242       // clang will use it instead.
243       return sa; // expected-error {{use of undeclared identifier 'sa'}}
244     }
245   };
246 };
247 template struct D<A>;
248 
249 }
250 
251 namespace PR19233 {
252 template <class T>
253 struct A : T {
fooPR19233::A254   void foo() {
255     ::undef(); // expected-error {{no member named 'undef' in the global namespace}}
256   }
barPR19233::A257   void bar() {
258     ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}}
259   }
bazPR19233::A260   void baz() {
261     B::qux(); // expected-error {{no member named 'B' in 'PR19233::A<D>'}} \
262     // expected-warning {{unqualified lookup into dependent bases of class template 'A'}}
263   }
264 };
265 
266 struct B { void qux(); };
267 struct C : B { };
268 template struct A<C>; // No error!  B is a base of A<C>, and qux is available.
269 
270 struct D { };
271 template struct A<D>; // expected-note {{in instantiation of member function 'PR19233::A<PR19233::D>::baz' requested here}}
272 
273 }
274 
275 namespace nonmethod_missing_this {
276 template <typename T> struct Base { int y = 42; };
277 template <typename T> struct Derived : Base<T> {
278   int x = y; // expected-warning {{lookup into dependent bases}}
foononmethod_missing_this::Derived279   auto foo(int j) -> decltype(y * j) { // expected-warning {{lookup into dependent bases}}
280     return y * j; // expected-warning {{lookup into dependent bases}}
281   }
barnonmethod_missing_this::Derived282   int bar() {
283     return [&] { return y; }(); // expected-warning {{lookup into dependent bases}}
284   }
285 };
286 template struct Derived<int>;
287 }
288 
289 namespace typedef_in_base {
290 template <typename T> struct A { typedef T NameFromBase; };
291 template <typename T> struct B : A<T> {
292   NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
293 };
294 static_assert(sizeof(B<int>) == 4, "");
295 }
296 
297 namespace struct_in_base {
298 template <typename T> struct A { struct NameFromBase {}; };
299 template <typename T> struct B : A<T> {
300   NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
301 };
302 static_assert(sizeof(B<int>) == 1, "");
303 }
304 
305 namespace enum_in_base {
306 template <typename T> struct A { enum NameFromBase { X }; };
307 template <typename T> struct B : A<T> {
308   NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
309 };
310 static_assert(sizeof(B<int>) == sizeof(A<int>::NameFromBase), "");
311 }
312 
313 namespace two_types_in_base {
314 template <typename T> struct A { typedef T NameFromBase; }; // expected-note {{member type 'int' found by ambiguous name lookup}}
315 template <typename T> struct B { struct NameFromBase { T m; }; }; // expected-note {{member type 'two_types_in_base::B<int>::NameFromBase' found by ambiguous name lookup}}
316 template <typename T> struct C : A<T>, B<T> {
317   NameFromBase m; // expected-error {{member 'NameFromBase' found in multiple base classes of different types}} expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
318 };
319 static_assert(sizeof(C<int>) != 0, ""); // expected-note {{in instantiation of template class 'two_types_in_base::C<int>' requested here}}
320 }
321 
322 namespace type_and_decl_in_base {
323 template <typename T> struct A { typedef T NameFromBase; };
324 template <typename T> struct B { static const T NameFromBase = 42; };
325 template <typename T> struct C : A<T>, B<T> {
326   NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
327 };
328 }
329 
330 namespace classify_type_from_base {
331 template <typename T> struct A { struct NameFromBase {}; };
332 template <typename T> struct B : A<T> {
333   A<NameFromBase> m; // expected-warning {{found via unqualified lookup into dependent bases}}
334 };
335 }
336 
337 namespace classify_nontype_from_base {
338 // MSVC does not do lookup of non-type declarations from dependent template base
339 // classes.  The extra lookup only applies to types.
NameFromBaseclassify_nontype_from_base::A340 template <typename T> struct A { void NameFromBase() {} };
341 template <void (*F)()> struct B { };
342 template <typename T> struct C : A<T> {
343   B<C::NameFromBase> a; // correct
344   B<NameFromBase> b; // expected-error {{use of undeclared identifier 'NameFromBase'}}
345 };
346 }
347 
348 namespace template_in_base {
349 template <typename T> struct A {
350   template <typename U> struct NameFromBase { U x; };
351 };
352 template <typename T> struct B : A<T> {
353   // Correct form.
354   typename B::template NameFromBase<T> m;
355 };
356 template <typename T> struct C : A<T> {
357   // Incorrect form.
358   NameFromBase<T> m; // expected-error {{no template named 'NameFromBase'}}
359 };
360 }
361 
362 namespace type_in_inner_class_in_base {
363 template <typename T>
364 struct A {
365   struct B { typedef T NameFromBase; };
366 };
367 template <typename T>
368 struct C : A<T>::B { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
369 }
370 
371 namespace type_in_inner_template_class_in_base {
372 template <typename T>
373 struct A {
374   template <typename U> struct B { typedef U InnerType; };
375 };
376 template <typename T>
377 struct C : A<T>::template B<T> {
378   NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
379 };
380 }
381 
382 namespace have_nondependent_base {
383 template <typename T>
384 struct A {
385   // Nothing, lookup should fail.
386 };
387 template <typename T>
388 struct B : A<T> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
389 struct C : A<int> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
390 }
391 
392 namespace type_in_base_of_dependent_base {
393 struct A { typedef int NameFromBase; };
394 template <typename T>
395 struct B : A {};
396 template <typename T>
397 struct C : B<T> { NameFromBase m; }; // expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
398 }
399 
400 namespace type_in_second_dependent_base {
401 template <typename T>
402 struct A {};
403 template<typename T>
404 struct B { typedef T NameFromBase; };
405 template <typename T>
406 struct D : A<T>, B<T> { NameFromBase m; }; // expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
407 }
408 
409 namespace type_in_second_non_dependent_base {
410 struct A {};
411 struct B { typedef int NameFromBase; };
412 template<typename T>
413 struct C : A, B {};
414 template <typename T>
415 struct D : C<T> { NameFromBase m; }; // expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
416 }
417 
418 namespace type_in_virtual_base_of_dependent_base {
419 template <typename T>
420 struct A { typedef T NameFromBase; };
421 template <typename T>
422 struct B : virtual A<T> {};
423 template <typename T>
424 struct C : B<T>, virtual A<T> { NameFromBase m; }; // expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
425 C<int> c;
426 }
427 
428 namespace type_in_base_of_multiple_dependent_bases {
429 template <typename T>
430 struct A { typedef T NameFromBase; };
431 template <typename T>
432 struct B : public A<T> {};
433 template <typename T>
434 struct C : B<T>, public A<T> { NameFromBase m; }; // expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}} expected-warning {{direct base 'A<int>' is inaccessible due to ambiguity:}}
435 C<int> c; // expected-note {{in instantiation of template class 'type_in_base_of_multiple_dependent_bases::C<int>' requested here}}
436 }
437 
438 namespace type_in_dependent_base_of_non_dependent_type {
439 template<typename T> struct A { typedef int NameFromBase; };
440 template<typename T> struct B : A<T> {
441   struct C;
442   template<typename TT>
443   struct D : C {
444     NameFromBase m; // expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
445   };
446   struct E : C {
447     NameFromBase m; // expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
448   };
449 };
450 template<typename T> struct B<T>::C : B {
451   NameFromBase m; // expected-warning {{use of member 'NameFromBase' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
452 };
453 template<typename T> struct F : B<T>::C {
454   NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
455 };
456 }
457 
458 namespace lookup_in_function_contexts {
459 template <typename T> struct A { typedef T NameFromBase; };
460 template <typename T>
461 struct B : A<T> {
462   // expected-warning@+1 {{lookup into dependent bases}}
lateSpecifiedFunclookup_in_function_contexts::B463   static auto lateSpecifiedFunc() -> decltype(NameFromBase()) {
464     return {};
465   }
466 
memberFunclookup_in_function_contexts::B467   static void memberFunc() {
468     NameFromBase x; // expected-warning {{lookup into dependent bases}}
469   }
470 
funcLocalClasslookup_in_function_contexts::B471   static void funcLocalClass() {
472     struct X {
473       NameFromBase x; // expected-warning {{lookup into dependent bases}}
474     } y;
475   }
476 
localClassMethodlookup_in_function_contexts::B477   void localClassMethod() {
478     struct X {
479       void bar() {
480         NameFromBase m; // expected-warning {{lookup into dependent bases}}
481       }
482     } x;
483     x.bar();
484   }
485 
funcLambdalookup_in_function_contexts::B486   static void funcLambda() {
487     auto l = []() {
488       NameFromBase x; // expected-warning {{lookup into dependent bases}}
489     };
490     l();
491   }
492 
constexprFunclookup_in_function_contexts::B493   static constexpr int constexprFunc() {
494     NameFromBase x = {}; // expected-warning {{lookup into dependent bases}}
495     return sizeof(x);
496   }
497 
autoFunclookup_in_function_contexts::B498   static auto autoFunc() {
499     NameFromBase x; // expected-warning {{lookup into dependent bases}}
500     return x;
501   }
502 };
503 
504 // Force us to parse the methods.
505 template struct B<int>;
506 }
507 
508 namespace function_template_deduction {
509 // Overloaded function templates.
f()510 template <int N> int f() { return N; }
f()511 template <typename T> int f() { return sizeof(T); }
512 
513 // Dependent base class with type.
514 template <typename T>
515 struct A { typedef T NameFromBase; };
516 template <typename T>
517 struct B : A<T> {
518   // expected-warning@+1 {{found via unqualified lookup into dependent bases}}
519   int x = f<NameFromBase>();
520 };
521 
522 // Dependent base class with enum.
523 template <typename T> struct C { enum { NameFromBase = 4 }; };
524 template <typename T> struct D : C<T> {
525   // expected-warning@+1 {{use of undeclared identifier 'NameFromBase'; unqualified lookup into dependent bases}}
526   int x = f<NameFromBase>();
527 };
528 }
529 
530 namespace function_template_undef_impl {
531 template<class T>
f()532 void f() {
533   Undef::staticMethod(); // expected-error {{use of undeclared identifier 'Undef'}}
534   UndefVar.method(); // expected-error {{use of undeclared identifier 'UndefVar'}}
535 }
536 }
537 
538 namespace PR20716 {
539 template <template <typename T> class A>
540 struct B : A<int>
541 {
542   XXX x; // expected-error {{unknown type name}}
543 };
544 
545 template <typename T>
546 struct C {};
547 
548 template <typename T>
549 using D = C<T>;
550 
551 template <typename T>
552 struct E : D<T>
553 {
554   XXX x; // expected-error {{unknown type name}}
555 };
556 }
557 
558 namespace PR23810 {
559 void f(int);
560 struct Base {
561   void f(); // expected-note{{must qualify identifier to find this declaration in dependent base class}}
562 };
563 template <typename T> struct Template : T {
memberPR23810::Template564   void member() {
565     f(); // expected-warning {{found via unqualified lookup into dependent bases}}
566   }
567 };
test()568 void test() {
569   Template<Base> x;
570   x.member(); // expected-note{{requested here}}
571 };
572 }
573 
574 namespace PR23823 {
575 // Don't delay lookup in SFINAE context.
576 template <typename T> decltype(g(T())) check(); // expected-note{{candidate template ignored: substitution failure [with T = int]: use of undeclared identifier 'g'}}
577 decltype(check<int>()) x; // expected-error{{no matching function for call to 'check'}}
578 
579 void h();
580 template <typename T> decltype(h(T())) check2(); // expected-note{{candidate template ignored: substitution failure [with T = int]: no matching function for call to 'h'}}
581 decltype(check2<int>()) y; // expected-error{{no matching function for call to 'check2'}}
582 }
583 
584 // We also allow unqualified lookup into bases in contexts where the we know the
585 // undeclared identifier *must* be a type, such as a new expression or catch
586 // parameter type.
587 template <typename T>
588 struct UseUnqualifiedTypeNames : T {
fooUseUnqualifiedTypeNames589   void foo() {
590     void *P = new TheType; // expected-warning {{unqualified lookup}} expected-error {{no type}}
591     size_t x = __builtin_offsetof(TheType, f2); // expected-warning {{unqualified lookup}} expected-error {{no type}}
592     try {
593     } catch (TheType) { // expected-warning {{unqualified lookup}} expected-error {{no type}}
594     }
595     enum E : IntegerType { E0 = 42 }; // expected-warning {{unqualified lookup}} expected-error {{no type}}
596     _Atomic(TheType) a; // expected-warning {{unqualified lookup}} expected-error {{no type}}
597   }
598   void out_of_line();
599 };
600 template <typename T>
out_of_line()601 void UseUnqualifiedTypeNames<T>::out_of_line() {
602   void *p = new TheType; // expected-warning {{unqualified lookup}} expected-error {{no type}}
603 }
604 struct Base {
605   typedef int IntegerType;
606   struct TheType {
607     int f1, f2;
608   };
609 };
610 template struct UseUnqualifiedTypeNames<Base>;
611 struct BadBase { };
612 template struct UseUnqualifiedTypeNames<BadBase>; // expected-note-re 2 {{in instantiation {{.*}} requested here}}
613 
614 namespace partial_template_lookup {
615 
616 class Bar;
617 class Spare;
618 
619 template <class T, class X = Bar>
620 class FooTemplated;
621 
622 class FooBase {
623 public:
624   typedef int BaseTypedef;
625 };
626 
627 // Partial template spec (unused)
628 template <class T>
629 class FooTemplated<T, Spare> {};
630 
631 // Partial template spec (used)
632 template <class T>
633 class FooTemplated<T, Bar> : public FooBase {};
634 
635 // Full template spec
636 template <class T, class X>
637 class FooTemplated : public FooTemplated<T, Bar> {
638 public:
639   BaseTypedef Member; // expected-warning {{unqualified lookup}}
640 };
641 }
642