Home | History | Annotate | Download | only in SemaTemplate
      1 // RUN: %clang_cc1 -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s
      2 
      3 
      4 template <class T>
      5 class A {
      6 public:
      7    void f(T a) { }// expected-note {{must qualify identifier to find this declaration in dependent base class}}
      8    void g();// expected-note {{must qualify identifier to find this declaration in dependent base class}}
      9 };
     10 
     11 template <class T>
     12 class B : public A<T> {
     13 public:
     14 	void z(T a)
     15     {
     16        f(a); // expected-warning {{use of identifier 'f' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
     17        g(); // expected-warning {{use of identifier 'g' found via unqualified lookup into dependent bases of class templates is a Microsoft extension}}
     18     }
     19 };
     20 
     21 template class B<int>; // expected-note {{requested here}}
     22 template class B<char>;
     23 
     24 void test()
     25 {
     26     B<int> b;
     27     b.z(3);
     28 }
     29 
     30 struct 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 };
     36 template void A2::f(int);
     37 
     38 template<class T0>
     39 struct A3 {
     40   template<class T1> void f(T1) {
     41     XX; //expected-error {{use of undeclared identifier 'XX'}}
     42   }
     43 };
     44 template void A3<int>::f(int);
     45 
     46 template<class T0>
     47 struct A4 {
     48   void f(char) {
     49     XX; //expected-error {{use of undeclared identifier 'XX'}}
     50   }
     51 };
     52 template class A4<int>;
     53 
     54 
     55 namespace lookup_dependent_bases_id_expr {
     56 
     57 template<class T> class A {
     58 public:
     59   int var;
     60 };
     61 
     62 
     63 template<class T>
     64 class B : public A<T> {
     65 public:
     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 
     71 template class B<int>;
     72 
     73 }
     74 
     75 
     76 
     77 namespace lookup_dependent_base_class_static_function {
     78 
     79 template <class T>
     80 class A {
     81 public:
     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 
     87 template <class T>
     88 class B : public A<T> {
     89 public:
     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 };
     95 template class B<int>; // expected-note {{requested here}}
     96 
     97 }
     98 
     99 
    100 
    101 namespace lookup_dependent_base_class_default_argument {
    102 
    103 template<class T>
    104 class A {
    105 public:
    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 
    110 template<class T>
    111 class B : public A<T> {
    112 public:
    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 
    117 void 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 
    127 namespace lookup_dependent_base_class_friend {
    128 
    129 template <class T>
    130 class B {
    131 public:
    132   static void g();  // expected-note {{must qualify identifier to find this declaration in dependent base class}}
    133 };
    134 
    135 template <class T>
    136 class A : public B<T> {
    137 public:
    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 
    143 int main2()
    144 {
    145   A<int> a;
    146   foo(a); // expected-note {{requested here}}
    147 }
    148 
    149 }
    150 
    151 
    152 namespace lookup_dependent_base_no_typo_correction {
    153 
    154 class C {
    155 public:
    156   int m_hWnd;
    157 };
    158 
    159 template <class T>
    160 class A : public T {
    161 public:
    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 
    167 template class A<C>;
    168 
    169 }
    170 
    171 namespace PR12701 {
    172 
    173 class A {};
    174 class B {};
    175 
    176 template <class T>
    177 class 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 
    183 template <class T>
    184 class 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 
    192 void 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 
    200 namespace PR16014 {
    201 
    202 struct A {
    203   int a;
    204   static int sa;
    205 };
    206 template <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 
    218 template <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 };
    225 
    226 template struct B<A>;
    227 template struct C<A>;  // expected-note-re 1+ {{in instantiation of member function 'PR16014::C<PR16014::A>::{{.*}}' requested here}}
    228 
    229 template <typename T> struct D : T {
    230   struct Inner {
    231     int foo() {
    232       // FIXME: MSVC can find this in D's base T!  Even worse, if ::sa exists,
    233       // clang will use it instead.
    234       return sa; // expected-error {{use of undeclared identifier 'sa'}}
    235     }
    236   };
    237 };
    238 template struct D<A>;
    239 
    240 }
    241 
    242 namespace PR19233 {
    243 template <class T>
    244 struct A : T {
    245   void foo() {
    246     ::undef(); // expected-error {{no member named 'undef' in the global namespace}}
    247   }
    248   void bar() {
    249     ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}}
    250   }
    251   void baz() {
    252     B::qux(); // expected-error {{use of undeclared identifier 'B'}}
    253   }
    254 };
    255 
    256 struct B { void qux(); };
    257 struct C : B { };
    258 template struct A<C>; // No error!  B is a base of A<C>, and qux is available.
    259 
    260 struct D { };
    261 template struct A<D>; // expected-note {{in instantiation of member function 'PR19233::A<PR19233::D>::baz' requested here}}
    262 
    263 }
    264 
    265 namespace nonmethod_missing_this {
    266 template <typename T> struct Base { int y = 42; };
    267 template <typename T> struct Derived : Base<T> {
    268   int x = y; // expected-warning {{lookup into dependent bases}}
    269   auto foo(int j) -> decltype(y * j) { // expected-warning {{lookup into dependent bases}}
    270     return y * j; // expected-warning {{lookup into dependent bases}}
    271   }
    272   int bar() {
    273     return [&] { return y; }(); // expected-warning {{lookup into dependent bases}}
    274   }
    275 };
    276 template struct Derived<int>;
    277 }
    278 
    279 namespace typedef_in_base {
    280 template <typename T> struct A { typedef T NameFromBase; };
    281 template <typename T> struct B : A<T> {
    282   NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
    283 };
    284 static_assert(sizeof(B<int>) == 4, "");
    285 }
    286 
    287 namespace struct_in_base {
    288 template <typename T> struct A { struct NameFromBase {}; };
    289 template <typename T> struct B : A<T> {
    290   NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
    291 };
    292 static_assert(sizeof(B<int>) == 1, "");
    293 }
    294 
    295 namespace enum_in_base {
    296 template <typename T> struct A { enum NameFromBase { X }; };
    297 template <typename T> struct B : A<T> {
    298   NameFromBase m; // expected-warning {{found via unqualified lookup into dependent bases}}
    299 };
    300 static_assert(sizeof(B<int>) == sizeof(A<int>::NameFromBase), "");
    301 }
    302 
    303 namespace two_types_in_base {
    304 template <typename T> struct A { typedef T NameFromBase; };
    305 template <typename T> struct B { struct NameFromBase { T m; }; };
    306 template <typename T> struct C : A<T>, B<T> {
    307   NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
    308 };
    309 static_assert(sizeof(C<int>) == 4, "");
    310 }
    311 
    312 namespace type_and_decl_in_base {
    313 template <typename T> struct A { typedef T NameFromBase; };
    314 template <typename T> struct B { static const T NameFromBase = 42; };
    315 template <typename T> struct C : A<T>, B<T> {
    316   NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
    317 };
    318 }
    319 
    320 namespace classify_type_from_base {
    321 template <typename T> struct A { struct NameFromBase {}; };
    322 template <typename T> struct B : A<T> {
    323   A<NameFromBase> m; // expected-warning {{found via unqualified lookup into dependent bases}}
    324 };
    325 }
    326 
    327 namespace classify_nontype_from_base {
    328 // MSVC does not do lookup of non-type declarations from dependent template base
    329 // classes.  The extra lookup only applies to types.
    330 template <typename T> struct A { void NameFromBase() {} };
    331 template <void (*F)()> struct B { };
    332 template <typename T> struct C : A<T> {
    333   B<C::NameFromBase> a; // correct
    334   B<NameFromBase> b; // expected-error {{use of undeclared identifier 'NameFromBase'}}
    335 };
    336 }
    337 
    338 namespace template_in_base {
    339 template <typename T> struct A {
    340   template <typename U> struct NameFromBase { U x; };
    341 };
    342 template <typename T> struct B : A<T> {
    343   // Correct form.
    344   typename B::template NameFromBase<T> m;
    345 };
    346 template <typename T> struct C : A<T> {
    347   // Incorrect form.
    348   NameFromBase<T> m; // expected-error {{unknown type name 'NameFromBase'}}
    349   //expected-error@-1 {{expected member name or ';' after declaration specifiers}}
    350 };
    351 }
    352 
    353 namespace type_in_inner_class_in_base {
    354 template <typename T>
    355 struct A {
    356   struct B { typedef T NameFromBase; };
    357 };
    358 template <typename T>
    359 struct C : A<T>::B { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
    360 }
    361 
    362 namespace type_in_inner_template_class_in_base {
    363 template <typename T>
    364 struct A {
    365   template <typename U> struct B { typedef U InnerType; };
    366 };
    367 template <typename T>
    368 struct C : A<T>::template B<T> {
    369   NameFromBase m; // expected-error {{unknown type name 'NameFromBase'}}
    370 };
    371 }
    372 
    373 namespace have_nondependent_base {
    374 template <typename T>
    375 struct A {
    376   // Nothing, lookup should fail.
    377 };
    378 template <typename T>
    379 struct B : A<T> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
    380 struct C : A<int> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
    381 }
    382 
    383 namespace type_in_base_of_dependent_base {
    384 struct A { typedef int NameFromBase; };
    385 template <typename T>
    386 struct B : A {};
    387 // FIXME: MSVC accepts this.
    388 template <typename T>
    389 struct C : B<T> { NameFromBase m; }; // expected-error {{unknown type name 'NameFromBase'}}
    390 }
    391 
    392 namespace lookup_in_function_contexts {
    393 template <typename T> struct A { typedef T NameFromBase; };
    394 template <typename T>
    395 struct B : A<T> {
    396   // expected-warning@+1 {{lookup into dependent bases}}
    397   static auto lateSpecifiedFunc() -> decltype(NameFromBase()) {
    398     return {};
    399   }
    400 
    401   static void memberFunc() {
    402     NameFromBase x; // expected-warning {{lookup into dependent bases}}
    403   }
    404 
    405   static void funcLocalClass() {
    406     struct X {
    407       NameFromBase x; // expected-warning {{lookup into dependent bases}}
    408     } y;
    409   }
    410 
    411   void localClassMethod() {
    412     struct X {
    413       void bar() {
    414         NameFromBase m; // expected-warning {{lookup into dependent bases}}
    415       }
    416     } x;
    417     x.bar();
    418   }
    419 
    420   static void funcLambda() {
    421     auto l = []() {
    422       NameFromBase x; // expected-warning {{lookup into dependent bases}}
    423     };
    424     l();
    425   }
    426 
    427   static constexpr int constexprFunc() {
    428     NameFromBase x = {}; // expected-warning {{lookup into dependent bases}}
    429     return sizeof(x);
    430   }
    431 
    432   static auto autoFunc() {
    433     NameFromBase x; // expected-warning {{lookup into dependent bases}}
    434     return x;
    435   }
    436 };
    437 
    438 // Force us to parse the methods.
    439 template struct B<int>;
    440 }
    441 
    442 namespace function_template_deduction {
    443 // Overloaded function templates.
    444 template <int N> int f() { return N; }
    445 template <typename T> int f() { return sizeof(T); }
    446 
    447 // Dependent base class with type.
    448 template <typename T>
    449 struct A { typedef T NameFromBase; };
    450 template <typename T>
    451 struct B : A<T> {
    452   // expected-warning@+1 {{found via unqualified lookup into dependent bases}}
    453   int x = f<NameFromBase>();
    454 };
    455 
    456 // Dependent base class with enum.
    457 template <typename T> struct C { enum { NameFromBase = 4 }; };
    458 template <typename T> struct D : C<T> {
    459   // expected-warning@+1 {{use of undeclared identifier 'NameFromBase'; unqualified lookup into dependent bases}}
    460   int x = f<NameFromBase>();
    461 };
    462 }
    463