Clang Project

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