1 // RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s 2 3 namespace basic { 4 struct C { 5 static void foo2() {} 6 }; 7 template <typename T> 8 struct A { 9 typedef C D; 10 }; 11 12 template <typename T> 13 struct B : A<T> { 14 void foo() { 15 D::foo2(); // expected-warning {{use of undeclared identifier 'D'; unqualified lookup into dependent bases of class template 'B' is a Microsoft extension}} 16 } 17 }; 18 19 template struct B<int>; // Instantiation has no warnings. 20 } 21 22 namespace nested_nodep_base { 23 // There are limits to our hacks, MSVC accepts this, but we don't. 24 struct A { 25 struct D { static void foo2(); }; 26 }; 27 template <typename T> 28 struct B : T { 29 struct C { 30 void foo() { 31 D::foo2(); // expected-error {{use of undeclared identifier 'D'}} 32 } 33 }; 34 }; 35 36 template struct B<A>; // Instantiation has no warnings. 37 } 38 39 namespace nested_dep_base { 40 // We actually accept this because the inner class has a dependent base even 41 // though it isn't a template. 42 struct A { 43 struct D { static void foo2(); }; 44 }; 45 template <typename T> 46 struct B { 47 struct C : T { 48 void foo() { 49 D::foo2(); // expected-warning {{use of undeclared identifier 'D'; unqualified lookup into dependent bases of class template 'C' is a Microsoft extension}} 50 } 51 }; 52 }; 53 54 template struct B<A>; // Instantiation has no warnings. 55 } 56